Hướng dẫn is there static variable in python? - có biến tĩnh trong python không?

Phương pháp tĩnh và lớp học

Như các câu trả lời khác đã lưu ý, các phương pháp tĩnh và lớp dễ dàng được thực hiện bằng cách sử dụng các nhà trang trí tích hợp:

class Test(object):

    # regular instance method:
    def my_method(self):
        pass

    # class method:
    @classmethod
    def my_class_method(cls):
        pass

    # static method:
    @staticmethod
    def my_static_method():
        pass

Như thường lệ, đối số đầu tiên cho

class Test(object):
    i = 3  # This is a class attribute

x = Test()
x.i = 12   # Attempt to change the value of the class attribute using x instance
assert x.i == Test.i  # ERROR
assert Test.i == 3    # Test.i was not affected
assert x.i == 12      # x.i is a different object than Test.i
2 bị ràng buộc với đối tượng thể hiện lớp. Ngược lại, đối số đầu tiên với
class Test(object):
    i = 3  # This is a class attribute

x = Test()
x.i = 12   # Attempt to change the value of the class attribute using x instance
assert x.i == Test.i  # ERROR
assert Test.i == 3    # Test.i was not affected
assert x.i == 12      # x.i is a different object than Test.i
3 bị ràng buộc với chính đối tượng lớp (ví dụ: trong trường hợp này,
class Test(object):
    i = 3  # This is a class attribute

x = Test()
x.i = 12   # Attempt to change the value of the class attribute using x instance
assert x.i == Test.i  # ERROR
assert Test.i == 3    # Test.i was not affected
assert x.i == 12      # x.i is a different object than Test.i
4). Đối với
class Test(object):
    i = 3  # This is a class attribute

x = Test()
x.i = 12   # Attempt to change the value of the class attribute using x instance
assert x.i == Test.i  # ERROR
assert Test.i == 3    # Test.i was not affected
assert x.i == 12      # x.i is a different object than Test.i
5, không có đối số nào bị ràng buộc và có các đối số là tùy chọn.

"Biến tĩnh"

Tuy nhiên, việc thực hiện "các biến tĩnh" (tốt, các biến tĩnh có thể thay đổi, dù sao đi nữa, nếu đó không phải là một mâu thuẫn trong các điều khoản ...) không phải là thẳng về phía trước. Như Millerdev đã chỉ ra trong câu trả lời của mình, vấn đề là các thuộc tính lớp của Python không thực sự là "biến tĩnh". Xem xét:

class Test(object):
    i = 3  # This is a class attribute

x = Test()
x.i = 12   # Attempt to change the value of the class attribute using x instance
assert x.i == Test.i  # ERROR
assert Test.i == 3    # Test.i was not affected
assert x.i == 12      # x.i is a different object than Test.i

Điều này là do dòng

class Test(object):
    i = 3  # This is a class attribute

x = Test()
x.i = 12   # Attempt to change the value of the class attribute using x instance
assert x.i == Test.i  # ERROR
assert Test.i == 3    # Test.i was not affected
assert x.i == 12      # x.i is a different object than Test.i
6 đã thêm một thuộc tính thể hiện mới
class Test(object):
    i = 3  # This is a class attribute

x = Test()
x.i = 12   # Attempt to change the value of the class attribute using x instance
assert x.i == Test.i  # ERROR
assert Test.i == 3    # Test.i was not affected
assert x.i == 12      # x.i is a different object than Test.i
7 vào
class Test(object):
    i = 3  # This is a class attribute

x = Test()
x.i = 12   # Attempt to change the value of the class attribute using x instance
assert x.i == Test.i  # ERROR
assert Test.i == 3    # Test.i was not affected
assert x.i == 12      # x.i is a different object than Test.i
8 thay vì thay đổi giá trị của thuộc tính
class Test(object):
    i = 3  # This is a class attribute

x = Test()
x.i = 12   # Attempt to change the value of the class attribute using x instance
assert x.i == Test.i  # ERROR
assert Test.i == 3    # Test.i was not affected
assert x.i == 12      # x.i is a different object than Test.i
4
class Test(object):
    i = 3  # This is a class attribute

x = Test()
x.i = 12   # Attempt to change the value of the class attribute using x instance
assert x.i == Test.i  # ERROR
assert Test.i == 3    # Test.i was not affected
assert x.i == 12      # x.i is a different object than Test.i
7.

Một phần hành vi biến tĩnh dự kiến, tức là, đồng bộ hóa thuộc tính giữa nhiều trường hợp (nhưng không phải với chính lớp; xem "Gotcha" bên dưới), có thể đạt được bằng cách biến thuộc tính lớp thành thuộc tính:not with the class itself; see "gotcha" below), can be achieved by turning the class attribute into a property:

class Test(object):

    _i = 3

    @property
    def i(self):
        return type(self)._i

    @i.setter
    def i(self,val):
        type(self)._i = val

## ALTERNATIVE IMPLEMENTATION - FUNCTIONALLY EQUIVALENT TO ABOVE ##
## (except with separate methods for getting and setting i) ##

class Test(object):

    _i = 3

    def get_i(self):
        return type(self)._i

    def set_i(self,val):
        type(self)._i = val

    i = property(get_i, set_i)

Bây giờ bạn có thể làm:

x1 = Test()
x2 = Test()
x1.i = 50
assert x2.i == x1.i  # no error
assert x2.i == 50    # the property is synced

Biến tĩnh bây giờ sẽ vẫn đồng bộ giữa tất cả các trường hợp lớp.

.

Lưu ý rằng về mặt kỹ thuật,

class Test(object):
    i = 3  # This is a class attribute

x = Test()
x.i = 12   # Attempt to change the value of the class attribute using x instance
assert x.i == Test.i  # ERROR
assert Test.i == 3    # Test.i was not affected
assert x.i == 12      # x.i is a different object than Test.i
7 vẫn hoàn toàn không phải là 'biến tĩnh'; Đó là một
class Test(object):

    _i = 3

    @property
    def i(self):
        return type(self)._i

    @i.setter
    def i(self,val):
        type(self)._i = val

## ALTERNATIVE IMPLEMENTATION - FUNCTIONALLY EQUIVALENT TO ABOVE ##
## (except with separate methods for getting and setting i) ##

class Test(object):

    _i = 3

    def get_i(self):
        return type(self)._i

    def set_i(self,val):
        type(self)._i = val

    i = property(get_i, set_i)
3, là một loại mô tả đặc biệt. Tuy nhiên, hành vi
class Test(object):

    _i = 3

    @property
    def i(self):
        return type(self)._i

    @i.setter
    def i(self,val):
        type(self)._i = val

## ALTERNATIVE IMPLEMENTATION - FUNCTIONALLY EQUIVALENT TO ABOVE ##
## (except with separate methods for getting and setting i) ##

class Test(object):

    _i = 3

    def get_i(self):
        return type(self)._i

    def set_i(self,val):
        type(self)._i = val

    i = property(get_i, set_i)
3 hiện tương đương với biến tĩnh (có thể thay đổi) được đồng bộ hóa trên tất cả các trường hợp lớp.

"Biến tĩnh" bất biến "

Đối với hành vi biến tĩnh bất biến, chỉ cần bỏ qua

class Test(object):

    _i = 3

    @property
    def i(self):
        return type(self)._i

    @i.setter
    def i(self,val):
        type(self)._i = val

## ALTERNATIVE IMPLEMENTATION - FUNCTIONALLY EQUIVALENT TO ABOVE ##
## (except with separate methods for getting and setting i) ##

class Test(object):

    _i = 3

    def get_i(self):
        return type(self)._i

    def set_i(self,val):
        type(self)._i = val

    i = property(get_i, set_i)
3 setter:

class Test(object):

    _i = 3

    @property
    def i(self):
        return type(self)._i

## ALTERNATIVE IMPLEMENTATION - FUNCTIONALLY EQUIVALENT TO ABOVE ##
## (except with separate methods for getting i) ##

class Test(object):

    _i = 3

    def get_i(self):
        return type(self)._i

    i = property(get_i)

Bây giờ cố gắng đặt thuộc tính

class Test(object):
    i = 3  # This is a class attribute

x = Test()
x.i = 12   # Attempt to change the value of the class attribute using x instance
assert x.i == Test.i  # ERROR
assert Test.i == 3    # Test.i was not affected
assert x.i == 12      # x.i is a different object than Test.i
7 sẽ trả về
class Test(object):

    _i = 3

    @property
    def i(self):
        return type(self)._i

    @i.setter
    def i(self,val):
        type(self)._i = val

## ALTERNATIVE IMPLEMENTATION - FUNCTIONALLY EQUIVALENT TO ABOVE ##
## (except with separate methods for getting and setting i) ##

class Test(object):

    _i = 3

    def get_i(self):
        return type(self)._i

    def set_i(self,val):
        type(self)._i = val

    i = property(get_i, set_i)
7:

x = Test()
assert x.i == 3  # success
x.i = 12         # ERROR

Một gotcha để nhận thức được

Lưu ý rằng các phương thức trên chỉ hoạt động với các phiên bản của lớp của bạn - chúng sẽ không hoạt động khi sử dụng chính lớp. Ví dụ:not work when using the class itself. So for example:

x = Test()
assert x.i == Test.i  # ERROR

# x.i and Test.i are two different objects:
type(Test.i)  # class 'property'
type(x.i)     # class 'int'

Dòng

class Test(object):

    _i = 3

    @property
    def i(self):
        return type(self)._i

    @i.setter
    def i(self,val):
        type(self)._i = val

## ALTERNATIVE IMPLEMENTATION - FUNCTIONALLY EQUIVALENT TO ABOVE ##
## (except with separate methods for getting and setting i) ##

class Test(object):

    _i = 3

    def get_i(self):
        return type(self)._i

    def set_i(self,val):
        type(self)._i = val

    i = property(get_i, set_i)
8 tạo ra một lỗi, bởi vì thuộc tính
class Test(object):
    i = 3  # This is a class attribute

x = Test()
x.i = 12   # Attempt to change the value of the class attribute using x instance
assert x.i == Test.i  # ERROR
assert Test.i == 3    # Test.i was not affected
assert x.i == 12      # x.i is a different object than Test.i
7 của
class Test(object):
    i = 3  # This is a class attribute

x = Test()
x.i = 12   # Attempt to change the value of the class attribute using x instance
assert x.i == Test.i  # ERROR
assert Test.i == 3    # Test.i was not affected
assert x.i == 12      # x.i is a different object than Test.i
4 và
class Test(object):
    i = 3  # This is a class attribute

x = Test()
x.i = 12   # Attempt to change the value of the class attribute using x instance
assert x.i == Test.i  # ERROR
assert Test.i == 3    # Test.i was not affected
assert x.i == 12      # x.i is a different object than Test.i
8 là hai đối tượng khác nhau.

Nhiều người sẽ thấy điều này đáng ngạc nhiên. Tuy nhiên, nó không nên được. Nếu chúng tôi quay lại và kiểm tra định nghĩa lớp

class Test(object):
    i = 3  # This is a class attribute

x = Test()
x.i = 12   # Attempt to change the value of the class attribute using x instance
assert x.i == Test.i  # ERROR
assert Test.i == 3    # Test.i was not affected
assert x.i == 12      # x.i is a different object than Test.i
4 của chúng tôi (phiên bản thứ hai), chúng tôi lưu ý dòng này:

    i = property(get_i) 

Rõ ràng, thành viên

class Test(object):
    i = 3  # This is a class attribute

x = Test()
x.i = 12   # Attempt to change the value of the class attribute using x instance
assert x.i == Test.i  # ERROR
assert Test.i == 3    # Test.i was not affected
assert x.i == 12      # x.i is a different object than Test.i
7 của
class Test(object):
    i = 3  # This is a class attribute

x = Test()
x.i = 12   # Attempt to change the value of the class attribute using x instance
assert x.i == Test.i  # ERROR
assert Test.i == 3    # Test.i was not affected
assert x.i == 12      # x.i is a different object than Test.i
4 phải là đối tượng
class Test(object):

    _i = 3

    @property
    def i(self):
        return type(self)._i

    @i.setter
    def i(self,val):
        type(self)._i = val

## ALTERNATIVE IMPLEMENTATION - FUNCTIONALLY EQUIVALENT TO ABOVE ##
## (except with separate methods for getting and setting i) ##

class Test(object):

    _i = 3

    def get_i(self):
        return type(self)._i

    def set_i(self,val):
        type(self)._i = val

    i = property(get_i, set_i)
3, đây là loại đối tượng được trả về từ hàm
class Test(object):

    _i = 3

    @property
    def i(self):
        return type(self)._i

    @i.setter
    def i(self,val):
        type(self)._i = val

## ALTERNATIVE IMPLEMENTATION - FUNCTIONALLY EQUIVALENT TO ABOVE ##
## (except with separate methods for getting and setting i) ##

class Test(object):

    _i = 3

    def get_i(self):
        return type(self)._i

    def set_i(self,val):
        type(self)._i = val

    i = property(get_i, set_i)
3.

Nếu bạn thấy những điều khó hiểu ở trên, rất có thể bạn vẫn đang nghĩ về nó từ quan điểm của các ngôn ngữ khác (ví dụ: Java hoặc C ++). Bạn nên đi nghiên cứu đối tượng

class Test(object):

    _i = 3

    @property
    def i(self):
        return type(self)._i

    @i.setter
    def i(self,val):
        type(self)._i = val

## ALTERNATIVE IMPLEMENTATION - FUNCTIONALLY EQUIVALENT TO ABOVE ##
## (except with separate methods for getting and setting i) ##

class Test(object):

    _i = 3

    def get_i(self):
        return type(self)._i

    def set_i(self,val):
        type(self)._i = val

    i = property(get_i, set_i)
3, về thứ tự mà các thuộc tính Python được trả về, giao thức mô tả và thứ tự độ phân giải phương thức (MRO).

Tôi trình bày một giải pháp cho 'gotcha' trên dưới đây; Tuy nhiên, tôi sẽ đề xuất - vất vả - rằng bạn không cố gắng làm điều gì đó như sau cho đến khi - tối thiểu - bạn hoàn toàn hiểu lý do tại sao

x1 = Test()
x2 = Test()
x1.i = 50
assert x2.i == x1.i  # no error
assert x2.i == 50    # the property is synced
8 gây ra lỗi.

Các biến tĩnh thực tế, thực tế - x1 = Test() x2 = Test() x1.i = 50 assert x2.i == x1.i # no error assert x2.i == 50 # the property is synced 9

Tôi trình bày giải pháp (Python 3) dưới đây cho mục đích thông tin. Tôi không tán thành nó như một "giải pháp tốt". Tôi nghi ngờ về việc liệu việc mô phỏng hành vi biến tĩnh của các ngôn ngữ khác trong Python có thực sự cần thiết hay không. Tuy nhiên, bất kể liệu nó có thực sự hữu ích hay không, dưới đây sẽ giúp hiểu thêm về cách thức hoạt động của Python.

Cập nhật: Nỗ lực này thực sự khá khủng khiếp; Nếu bạn khăng khăng làm một cái gì đó như thế này (gợi ý: Xin đừng; Python là một ngôn ngữ rất thanh lịch và đưa nó đi hành xử như một ngôn ngữ khác là không cần thiết), thay vào đó hãy sử dụng mã trong câu trả lời của Ethan Furman.is really pretty awful; if you insist on doing something like this (hint: please don't; Python is a very elegant language and shoe-horning it into behaving like another language is just not necessary), use the code in Ethan Furman's answer instead.

Mô phỏng hành vi biến tĩnh của các ngôn ngữ khác bằng cách sử dụng metaclass

Một metaclass là lớp của một lớp. Metaclass mặc định cho tất cả các lớp trong Python (tức là, các lớp "kiểu mới" đăng Python 2.3 tôi tin) là

class Test(object):

    _i = 3

    @property
    def i(self):
        return type(self)._i

## ALTERNATIVE IMPLEMENTATION - FUNCTIONALLY EQUIVALENT TO ABOVE ##
## (except with separate methods for getting i) ##

class Test(object):

    _i = 3

    def get_i(self):
        return type(self)._i

    i = property(get_i)
0. Ví dụ:

type(int)  # class 'type'
type(str)  # class 'type'
class Test(): pass
type(Test) # class 'type'

Tuy nhiên, bạn có thể xác định metaclass của riêng bạn như thế này:

class MyMeta(type): pass

Và áp dụng nó cho lớp của riêng bạn như thế này (chỉ Python 3):

class Test(object):
    i = 3  # This is a class attribute

x = Test()
x.i = 12   # Attempt to change the value of the class attribute using x instance
assert x.i == Test.i  # ERROR
assert Test.i == 3    # Test.i was not affected
assert x.i == 12      # x.i is a different object than Test.i
0

Dưới đây là một metaclass mà tôi đã tạo ra để cố gắng mô phỏng hành vi "biến tĩnh" của các ngôn ngữ khác. Về cơ bản, nó hoạt động bằng cách thay thế bộ getter, setter và deleter mặc định bằng các phiên bản kiểm tra xem có yêu cầu thuộc tính có phải là "biến tĩnh" không.

Một danh mục của "biến tĩnh" được lưu trữ trong thuộc tính

class Test(object):

    _i = 3

    @property
    def i(self):
        return type(self)._i

## ALTERNATIVE IMPLEMENTATION - FUNCTIONALLY EQUIVALENT TO ABOVE ##
## (except with separate methods for getting i) ##

class Test(object):

    _i = 3

    def get_i(self):
        return type(self)._i

    i = property(get_i)
1. Tất cả các yêu cầu thuộc tính ban đầu được cố gắng để được giải quyết bằng cách sử dụng thứ tự độ phân giải thay thế. Tôi đã đặt tên là "thứ tự độ phân giải tĩnh" hoặc "sro". Điều này được thực hiện bằng cách tìm kiếm thuộc tính được yêu cầu trong tập hợp "biến tĩnh" cho một lớp nhất định (hoặc các lớp cha của nó). Nếu thuộc tính không xuất hiện trong "SRO", lớp sẽ quay trở lại trên hành vi GET/SET/SET/Xóa thuộc tính mặc định (nghĩa là "MRO").

class Test(object):
    i = 3  # This is a class attribute

x = Test()
x.i = 12   # Attempt to change the value of the class attribute using x instance
assert x.i == Test.i  # ERROR
assert Test.i == 3    # Test.i was not affected
assert x.i == 12      # x.i is a different object than Test.i
1

Làm thế nào để bạn giữ một tĩnh khác nhau trong Python?

Một cách để giữ các biến tĩnh đồng bộ là làm cho chúng thuộc tính: kiểm tra lớp (đối tượng):, _i = 3, @Property, def i (self), return loại (tự).make them properties: class Test(object): , _i = 3 , @property , def i(self) , return type(self).

Các biến tĩnh được lưu trữ trong Python ở đâu?

Các biến cần thiết bên ngoài các cuộc gọi phương thức hoặc chức năng hoặc được chia sẻ trong nhiều chức năng trên toàn cầu được lưu trữ trong bộ nhớ heap.Heap memory.

Các biến tĩnh và động trong Python là gì?

Nếu loại biến được kiểm tra trong thời gian chạy của mã so với ngôn ngữ được gọi là ngôn ngữ được gõ động.Nếu loại biến được kiểm tra theo thời gian biên dịch của mã so với ngôn ngữ được gọi là ngôn ngữ được đánh máy tĩnh.

Tĩnh có nghĩa là gì trong Python?

Phương tiện tĩnh, rằng thành viên ở cấp độ lớp thay vì ở cấp độ.Các biến tĩnh chỉ tồn tại ở cấp độ lớp và không được khởi tạo.Nếu bạn thay đổi một biến tĩnh trong một trường hợp của lớp, thay đổi sẽ ảnh hưởng đến giá trị của nó trong tất cả các trường hợp khác.the member is on a class level rather on the instance level. Static variables exist only on class level and aren't instantiated. If you change a static variable in one instance of the class, the change will affect its value in all other instances.