Có thể chỉ khai báo một biến mà không gán bất kỳ giá trị nào trong Python không?


288

Có thể khai báo một biến trong Python, như vậy không?:

var

để nó khởi tạo thành Không? Có vẻ như Python cho phép điều này, nhưng ngay khi bạn truy cập, nó gặp sự cố. Điều này có thể không? Nếu không, tại sao?

EDIT: Tôi muốn làm điều này cho các trường hợp như thế này:

value

for index in sequence:

   if value == None and conditionMet:
       value = index
       break

Bản sao

Liên quan


1
có thể đăng một chương trình nhỏ gây ra điều này xin vui lòng.
Preet Sangha

Bạn đã đăng một câu hỏi trùng lặp, bỏ phiếu để đóng câu hỏi này có lợi cho câu hỏi khác.
Jerub

Vẫn còn một số khác biệt, điều này liên quan đến việc không thể sử dụng một biến chỉ bằng cách khai báo.
Joan Venge

Thực sự không có bất kỳ điều gì như khai báo một biến trong thế giới trăn, như câu hỏi đầu tiên của bạn giải thích.
Harley Holcombe

1
tại sao không ai từng nói 'chỉ cần gán cho nó' bởi vì các biến không tồn tại trước khi chúng được gán cho dấu chấm. Và các biến trong python không chứa thông tin loại. Đối tượng làm điều đó. Các biến chỉ để giữ đối tượng tại thời điểm đó. Hơn nữa, chương trình trên sẽ ném ngoại lệ NameError trên dòng đầu tiên. (Đó là những gì tôi nhận được trong 2.X và 3.X cả hai)
osirisgothra

Câu trả lời:


359

Tại sao không làm điều này:

var = None

Python rất năng động, vì vậy bạn không cần phải khai báo mọi thứ; chúng tồn tại tự động trong phạm vi đầu tiên nơi chúng được chỉ định. Vì vậy, tất cả những gì bạn cần là một tuyên bố chuyển nhượng cũ thông thường như trên.

Điều này là tốt, bởi vì bạn sẽ không bao giờ kết thúc với một biến chưa được khởi tạo. Nhưng hãy cẩn thận - điều này không có nghĩa là bạn sẽ không kết thúc với các biến được khởi tạo không chính xác . Nếu bạn khởi xướng điều gì đó None, hãy đảm bảo đó là điều bạn thực sự muốn và chỉ định điều gì đó có ý nghĩa hơn nếu bạn có thể.


1
Tôi sẽ làm điều đó, nhưng chỉ cần nghĩ rằng nó sẽ làm điều đó.
Joan Venge

7
Vấn đề là điều này phải rõ ràng, không ngầm định. Không đoán được giá trị ban đầu là gì. Không có thắc mắc nếu một biến chưa được khởi tạo ném một ngoại lệ hoặc kỳ diệu có một giá trị hữu ích.
S.Lott

2
Vấn đề duy nhất tôi gặp phải là tôi đang theo dõi một bộ đếm (minValue) và bất cứ khi nào giá trị thấp hơn nó, tôi sẽ đặt nó trở thành minValue mới. Nếu tôi tuyên bố minValue là Không có gì ban đầu, thì rõ ràng nó vẫn thấp hơn bất kỳ con số nào tôi so sánh với nó. Tôi đã kết thúc việc khởi tạo nó tại sys.maxint
TJ Biddle

... chúng tồn tại tự động trong phạm vi đầu tiên nơi chúng được chỉ định. Vì vậy, bạn phải săn lùng bài tập đầu tiên đó và tìm ra nó. ừ!
Ed Randall

56

Tôi chân thành khuyên bạn nên đọc các ngôn ngữ khác có "biến" (tôi đã thêm nó dưới dạng một liên kết có liên quan) - trong hai phút bạn sẽ biết rằng Python có "tên" chứ không phải "biến".

val = None
# ...
if val is None:
   val = any_object

Bạn cũng có thể viết val = val or any_objectđể khởi tạo nó.
Zoltán

1
@ Zoltán: nó phá vỡ nếu giá trị hợp lệ cho val là "false", ví dụ: 0 hoặc rỗng. Sử dụng isđể kiểm tra xem một giá trị là None.
jfs

Sau khi đọc bài viết tại liên kết được cung cấp, nó dường như ít hơn nhiều so với ngụy biện ngữ nghĩa.
Andrew P.

29

Trong Python 3.6+, bạn có thể sử dụng Chú thích biến cho việc này:

https://www.python.org/dev/peps/pep-0526/#abab

PEP 484 giới thiệu gợi ý loại, còn gọi là chú thích loại. Mặc dù trọng tâm chính của nó là chú thích chức năng, nó cũng đưa ra khái niệm nhận xét kiểu để chú thích các biến:

# 'captain' is a string (Note: initial value is a problem)
captain = ...  # type: str

PEP 526 nhằm mục đích thêm cú pháp vào Python để chú thích các loại biến (bao gồm biến lớp và biến thể hiện), thay vì thể hiện chúng thông qua các bình luận:

captain: str  # Note: no initial value!

Có vẻ như nó phù hợp hơn với những gì bạn đang hỏi "Có thể chỉ khai báo một biến mà không gán bất kỳ giá trị nào trong Python không?"


2
Câu trả lời tuyệt vời
Ben

16

Tôi không chắc chắn những gì bạn đang cố gắng làm. Python là một ngôn ngữ rất năng động; bạn thường không cần khai báo các biến cho đến khi bạn thực sự sẽ gán hoặc sử dụng chúng. Tôi nghĩ những gì bạn muốn làm chỉ là

foo = None

Nó sẽ gán giá trị Nonecho biến foo.

EDIT: Những gì bạn thực sự muốn làm chỉ là thế này:

#note how I don't do *anything* with value here
#we can just start using it right inside the loop

for index in sequence:
   if conditionMet:
       value = index
       break

try:
    doSomething(value)
except NameError:
    print "Didn't find anything"

Thật khó để nói liệu đó có thực sự là phong cách phù hợp để sử dụng từ một ví dụ mã ngắn như vậy không, nhưng đó cách làm việc "Pythonic" hơn.

EDIT: bên dưới là bình luận của JFS (đăng ở đây để hiển thị mã)

Không liên quan đến câu hỏi của OP nhưng đoạn mã trên có thể được viết lại thành:

for item in sequence:
    if some_condition(item): 
       found = True
       break
else: # no break or len(sequence) == 0
    found = False

if found:
   do_something(item)

LƯU Ý: nếu some_condition()tăng một ngoại lệ thì foundkhông bị ràng buộc.
LƯU Ý: nếu len (chuỗi) == 0 thì itemkhông bị ràng buộc.

Các mã trên không được khuyến khích. Mục đích của nó là để minh họa cách các biến cục bộ hoạt động, cụ thể là liệu "biến" được "xác định" chỉ có thể được xác định khi chạy trong trường hợp này. Cách tốt nhất:

for item in sequence:
    if some_condition(item):
       do_something(item)
       break

Hoặc là

found = False
for item in sequence:
    if some_condition(item):
       found = True
       break

if found:
   do_something(item)

Có sự khác biệt giữa một ngôn ngữ năng động và một ngôn ngữ rất năng động?
Gavin Miller

Có một bài viết tuyệt vời giải thích các trục khác nhau của việc gõ ngôn ngữ lập trình và cách chúng liên tục, không phải giá trị boolean; thật không may, tôi không bao giờ có thể tìm thấy bài viết đó một lần nữa khi tôi muốn trích dẫn nó :( Tôi coi Python "rất năng động" bởi vì nó nằm ở phía xa của nhiều trục.
kquinn

3

Tôi thường khởi tạo biến thành một cái gì đó biểu thị kiểu như

var = ""

hoặc là

var = 0

Nếu nó sẽ là một đối tượng thì đừng khởi tạo nó cho đến khi bạn khởi tạo nó:

var = Var()

3

Chà, nếu bạn muốn kiểm tra xem một biến có được xác định hay không thì tại sao không kiểm tra xem nó có nằm trong mảng cục bộ () hoặc globalals () không? Mã của bạn viết lại:

for index in sequence:
   if 'value' not in globals() and conditionMet:
       value = index
       break

Nếu đó là một biến cục bộ mà bạn đang tìm kiếm thì hãy thay thế globalals () bằng localals ().


2

Trước hết, câu trả lời của tôi cho câu hỏi ban đầu bạn đã hỏi

H: Làm thế nào để tôi khám phá nếu một biến được xác định tại một điểm trong mã của tôi?

A: Đọc trong tệp nguồn cho đến khi bạn thấy một dòng trong đó biến đó được xác định.

Nhưng xa hơn nữa, bạn đã đưa ra một ví dụ mã rằng có nhiều hoán vị khác nhau khá là pythonic. Bạn đang tìm cách quét một chuỗi các yếu tố phù hợp với một điều kiện, vì vậy đây là một số giải pháp:

def findFirstMatch(sequence):
    for value in sequence:
        if matchCondition(value):
            return value

    raise LookupError("Could not find match in sequence")

Rõ ràng trong ví dụ này, bạn có thể thay thế raisebằng một return Nonetùy thuộc vào những gì bạn muốn đạt được.

Nếu bạn muốn mọi thứ phù hợp với điều kiện, bạn có thể làm điều này:

def findAllMatches(sequence):
    matches = []
    for value in sequence:
        if matchCondition(value):
            matches.append(value)

    return matches

Có một cách khác để làm điều này với yieldđiều đó tôi sẽ không bận tâm chỉ cho bạn, bởi vì nó khá phức tạp trong cách nó hoạt động.

Hơn nữa, có một cách để đạt được điều này:

all_matches = [value for value in sequence if matchCondition(value)]

2

Nếu tôi hiểu đúng ví dụ của bạn, bạn không cần phải tham khảo 'giá trị' trong câu lệnh if. Bạn đang thoát ra khỏi vòng lặp ngay khi nó có thể được đặt thành bất cứ điều gì.

value = None
for index in sequence:
   doSomethingHere
   if conditionMet:
       value = index
       break 

1

Bạn trông giống như bạn đang cố gắng viết C bằng Python. Nếu bạn muốn tìm thứ gì đó theo trình tự, Python có các hàm dựng sẵn để làm điều đó, như

value = sequence.index(blarg)

1

Đó là một câu hỏi hay và không may là các câu trả lời xấu vì var = Noneđã gán một giá trị và nếu tập lệnh của bạn chạy nhiều lần thì nó sẽ bị ghi đè bằngNone mỗi lần.

Nó không giống như định nghĩa mà không có sự phân công. Tôi vẫn đang cố gắng tìm ra cách để vượt qua vấn đề này.


1

Có thể khai báo một biến trong Python (var = none):

def decl_var(var=None):
if var is None:
    var = []
var.append(1)
return var

0
var_str = str()
var_int = int()

người đàn ông nghịch ngợm nghịch ngợm! biến không liên kết loại, đối tượng làm. var_str không nên bị ràng buộc trong một tên chung như vậy. Nếu bạn định làm điều này, hãy làm cho nó có ý nghĩa như 'var_age' hoặc 'var_name' chẳng hạn. Các giá trị như vậy có thể được lấy dưới dạng số nguyên hoặc chuỗi hoặc bất cứ thứ gì bạn muốn và thay đổi thành các đối tượng, chính tinh thần của những gì làm cho python khác với các ngôn ngữ khác. Họ nói rằng nếu bạn thấy mình cần phải làm điều này mọi lúc, có lẽ bạn muốn sử dụng một số ngôn ngữ khác.
osirisgothra

0

Nếu Nonelà một giá trị dữ liệu hợp lệ thì bạn cần phải biến theo một cách khác. Bạn đã có thể sử dụng:

var = object()

Sentinel này được đề xuất bởi Nick Coghlan .


0

Bạn có thể lừa một trình thông dịch với oneliner xấu xí này. if None: var = None Nó không làm gì khác ngoài việc thêm một biến varvào từ điển biến cục bộ, không khởi tạo nó. Trình thông dịch sẽ đưa ra ngoại lệ UnboundLocalError nếu bạn cố gắng sử dụng biến này trong một hàm sau đó. Điều này cũng sẽ làm việc cho các phiên bản trăn rất cổ xưa. Không đơn giản, cũng không đẹp, nhưng đừng kỳ vọng nhiều vào con trăn.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.