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
x1 = Test[]
x2 = Test[]
x1.i = 50
assert x2.i == x1.i # no error
assert x2.i == 50 # the property is synced
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
0Dướ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