Vì vậy, tôi đang cố gắng tìm ra cách tốt nhất [thanh lịch nhất với số lượng mã ít nhất] để cho phép ghi đè các chức năng cụ thể của một thuộc tính [ví dụ: chỉ là getter, chỉ là setter, v.v.] trong Python. Tôi là một fan hâm mộ của cách thực hiện các thuộc tính sau đây, do thực tế là tất cả các phương thức của chúng được gói gọn trong cùng một khối mã được thụt vào bắt đầu tiếp theo]:
@apply
def foo[]:
"""A foobar"""
def fget[self]:
return self._foo
def fset[self, val]:
self._foo = val
return property[**locals[]]
Tuy nhiên, nếu tôi muốn kế thừa từ một lớp xác định các thuộc tính theo cách này, và sau đó, nói, ghi đè chức năng setter
>>> a = A[]
>>> a.foo
8
>>> b = ATimesTwo[]
>>> b.foo
16
3, nó có vẻ khó khăn. Tôi đã thực hiện một số tìm kiếm và hầu hết các câu trả lời tôi đã tìm thấy là xác định các chức năng riêng biệt trong lớp cơ sở [ví dụ: >>> a = A[]
>>> a.foo
8
>>> b = ATimesTwo[]
>>> b.foo
16
4 và >>> a = A[]
>>> a.foo
8
>>> b = ATimesTwo[]
>>> b.foo
16
5], tạo rõ ràng định nghĩa thuộc tính từ chúng [ví dụ: >>> a = A[]
>>> a.foo
8
>>> b = ATimesTwo[]
>>> b.foo
16
6] và sau đó ghi đè >>> a = A[]
>>> a.foo
8
>>> b = ATimesTwo[]
>>> b.foo
16
4, >>> a = A[]
>>> a.foo
8
>>> b = ATimesTwo[]
>>> b.foo
16
5 và >>> a = A[]
>>> a.foo
8
>>> b = ATimesTwo[]
>>> b.foo
16
9 khi cần thiết.Tôi không thích giải pháp này vì điều đó có nghĩa là tôi phải định nghĩa Lambas cho mỗi thuộc tính, và sau đó viết ra từng cuộc gọi chức năng [khi trước khi tôi có thể thực hiện
class C[object]: def __init__[self]: self._x = None @property def x[self]: return self._x @x.setter def x[self, value]: self._x = value @x.deleter def x[self]: del self._x0]. Tôi cũng không nhận được sự đóng gói mà ban đầu tôi đã có.
Lý tưởng nhất, những gì tôi muốn có thể làm sẽ là một cái gì đó như thế này:
class A[object]:
def __init__[self]:
self.foo = 8
@apply
def foo[]:
"""A foobar"""
def fget[self]:
return self._foo
def fset[self, val]:
self._foo = val
return property[**locals[]]
class ATimesTwo[A]:
@some_decorator
def foo[]:
def fset[self, val]:
self._foo = val * 2
return something
Và sau đó, đầu ra sẽ trông giống như:
>>> a = A[]
>>> a.foo
8
>>> b = ATimesTwo[]
>>> b.foo
16
Về cơ bản,
class C[object]: def __init__[self]: self._x = None @property def x[self]: return self._x @x.setter def x[self, value]: self._x = value @x.deleter def x[self]: del self._x1 kế thừa hàm getter từ
class C[object]: def __init__[self]: self._x = None @property def x[self]: return self._x @x.setter def x[self, value]: self._x = value @x.deleter def x[self]: del self._x2 nhưng ghi đè chức năng setter. Có ai biết cách làm điều này [theo cách trông giống với ví dụ trên] không?
class C[object]: def __init__[self]: self._x = None @property def x[self]: return self._x @x.setter def x[self, value]: self._x = value @x.deleter def x[self]: del self._x3 sẽ trông như thế nào, và chức năng
>>> a = A[]
>>> a.foo
8
>>> b = ATimesTwo[]
>>> b.foo
16
3 nên trả về? Các tài liệu Python trên class C[object]:
def __init__[self]:
self._x = None
@property
def x[self]:
return self._x
@x.setter
def x[self, value]:
self._x = value
@x.deleter
def x[self]:
del self._x
5 Trang trí cho thấy thành ngữ sau:
class C[object]: def __init__[self]: self._x = None @property def x[self]: return self._x @x.setter def x[self, value]: self._x = value @x.deleter def x[self]: del self._x
Và sau đó các lớp con có thể ghi đè một setter/getter duy nhất như thế này:
class C2[C]: @C.x.getter def x[self]: return self._x * -1
Đây là một chút warty vì việc ghi đè nhiều phương thức dường như yêu cầu bạn phải làm một cái gì đó như:
class C3[C]: @C.x.getter def x[self]: return self._x * -1 # C3 now has an x property with a modified getter # so modify its setter rather than C.x 's setter. @x.setter def x[self, value]: self._x = value * 2
Tôi chắc chắn rằng bạn đã nghe điều này trước đây, nhưng
class C[object]: def __init__[self]: self._x = None @property def x[self]: return self._x @x.setter def x[self, value]: self._x = value @x.deleter def x[self]: del self._x6 đã bị phản đối trong tám năm, kể từ Python 2.3. Không sử dụng nó. Việc bạn sử dụng
class C[object]: def __init__[self]: self._x = None @property def x[self]: return self._x @x.setter def x[self, value]: self._x = value @x.deleter def x[self]: del self._x7 cũng trái với Zen of Python - rõ ràng là tốt hơn tiềm ẩn. Nếu bạn thực sự thích vết lõm tăng lên, không cần phải tạo ra một đối tượng vứt bỏ, chỉ cần làmfor eight years, since Python 2.3. Don't use it. Your use of
class C[object]: def __init__[self]: self._x = None @property def x[self]: return self._x @x.setter def x[self, value]: self._x = value @x.deleter def x[self]: del self._x7 is also contrary to the Zen of Python -- explicit is better than implicit. If you really like the increased indentation, there is no need to create a throwaway object, just do
if True: @property def foo[self]: return self._foo @foo.setter def foo[self, val]: self._foo = val
Nếu lớp con biết thuộc tính được xác định ở đâu, chỉ cần làm:
class ATimesTwo[A]: @A.foo.setter def foo[self, val]: self._foo = val * 2
Ví dụ cho một thuộc tính hỗ trợ nối thêm các phương thức cho các chức năng đã đặt:
class ExtendableProperty[property]: def append_setter[self, fset]: # Create a wrapper around the new fset that also calls the current fset _old_fset = self.fset def _appended_setter[obj, value]: _old_fset[obj, value] fset[obj, value] # Use that wrapper as setter instead of only the new fset return self.setter[_appended_setter]
Việc sử dụng giống như đối với các thuộc tính bình thường, chỉ bây giờ có thể thêm các phương thức vào các setters thuộc tính:
class A[object]: @ExtendableProperty def prop[self]: return self._prop @prop.setter def prop[self, v]: self._prop = v class B[A]: @A.prop.append_setter def prop[self, v]: print['Set', v]
class A[object]:
def __init__[self]:
self.foo = 8
@apply
def foo[]:
"""A foobar"""
def fget[self]:
return self._foo
def fset[self, val]:
self._foo = val
return property[**locals[]]
class ATimesTwo[A]:
@some_decorator
def foo[]:
def fset[self, val]:
self._foo = val * 2
return something
0Gợi ý: 2
Chỉ ghi đè một getter, setter hoặc một đối tượng thuộc tính, chỉ ghi đè lên một getter, setter hoặc một dấu hiệu của một đối tượng thuộc tính, bắt đầu với ngôn ngữ Python, bắt đầu với ngôn ngữ Python
Khi bạn kế thừa từ một lớp có tài sản, bạn có thể cung cấp một triển khai mới cho một hoặc nhiều chức năng
class C[object]: def __init__[self]: self._x = None @property def x[self]: return self._x @x.setter def x[self, value]: self._x = value @x.deleter def x[self]: del self._x8,
class C[object]: def __init__[self]: self._x = None @property def x[self]: return self._x @x.setter def x[self, value]: self._x = value @x.deleter def x[self]: del self._x9 hoặc
class C2[C]: @C.x.getter def x[self]: return self._x * -10, bằng cách tham chiếu đối tượng thuộc tính trên lớp cha:
class A[object]:
def __init__[self]:
self.foo = 8
@apply
def foo[]:
"""A foobar"""
def fget[self]:
return self._foo
def fset[self, val]:
self._foo = val
return property[**locals[]]
class ATimesTwo[A]:
@some_decorator
def foo[]:
def fset[self, val]:
self._foo = val * 2
return something
1Gợi ý: 3
Vì vậy, tôi đang cố gắng tìm ra cách tốt nhất [thanh lịch nhất với số lượng mã ít nhất] để cho phép ghi đè các chức năng cụ thể của một thuộc tính [ví dụ: chỉ là getter, chỉ là setter, v.v.] trong Python. Tôi là một fan hâm mộ của cách thực hiện các thuộc tính sau đây, do thực tế là tất cả các phương thức của chúng được gói gọn trong cùng một khối mã được thụt vào tiếp theo bắt đầu] :, tất nhiên tại điểm mà bạn đang ghi đè Getter, Setter và Deleter Bạn có thể chỉ cần xác định lại thuộc tính cho C3., Tôi không thích giải pháp này vì điều đó có nghĩa là tôi phải xác định Lambas cho mọi thuộc tính và Sau đó viết ra mỗi cuộc gọi chức năng [khi trước khi tôi có thể thực hiện thuộc tính [** locals []]]. Tôi cũng không nhận được sự đóng gói mà ban đầu tôi đã có.
Vì vậy, tôi đang cố gắng tìm ra cách tốt nhất [thanh lịch nhất với số lượng mã ít nhất] để cho phép ghi đè các chức năng cụ thể của một thuộc tính [ví dụ: chỉ là getter, chỉ là setter, v.v.] trong Python. Tôi là một fan hâm mộ của cách thực hiện các thuộc tính sau đây, do thực tế là tất cả các phương thức của chúng được gói gọn trong cùng một khối mã được thụt vào bắt đầu tiếp theo]:
class A[object]:
def __init__[self]:
self.foo = 8
@apply
def foo[]:
"""A foobar"""
def fget[self]:
return self._foo
def fset[self, val]:
self._foo = val
return property[**locals[]]
class ATimesTwo[A]:
@some_decorator
def foo[]:
def fset[self, val]:
self._foo = val * 2
return something
2Lý tưởng nhất, những gì tôi muốn có thể làm sẽ là một cái gì đó như thế này:
class A[object]:
def __init__[self]:
self.foo = 8
@apply
def foo[]:
"""A foobar"""
def fget[self]:
return self._foo
def fset[self, val]:
self._foo = val
return property[**locals[]]
class ATimesTwo[A]:
@some_decorator
def foo[]:
def fset[self, val]:
self._foo = val * 2
return something
3Và sau đó, đầu ra sẽ trông giống như:
class A[object]:
def __init__[self]:
self.foo = 8
@apply
def foo[]:
"""A foobar"""
def fget[self]:
return self._foo
def fset[self, val]:
self._foo = val
return property[**locals[]]
class ATimesTwo[A]:
@some_decorator
def foo[]:
def fset[self, val]:
self._foo = val * 2
return something
4Các tài liệu Python trên
class C[object]: def __init__[self]: self._x = None @property def x[self]: return self._x @x.setter def x[self, value]: self._x = value @x.deleter def x[self]: del self._x5 Trang trí cho thấy thành ngữ sau:
class C[object]: def __init__[self]: self._x = None @property def x[self]: return self._x @x.setter def x[self, value]: self._x = value @x.deleter def x[self]: del self._x
Và sau đó các lớp con có thể ghi đè một setter/getter duy nhất như thế này:
class C2[C]: @C.x.getter def x[self]: return self._x * -1
Đây là một chút warty vì việc ghi đè nhiều phương thức dường như yêu cầu bạn phải làm một cái gì đó như:
class C3[C]: @C.x.getter def x[self]: return self._x * -1 # C3 now has an x property with a modified getter # so modify its setter rather than C.x 's setter. @x.setter def x[self, value]: self._x = value * 2
Tôi chắc chắn rằng bạn đã nghe điều này trước đây, nhưng class C[object]:
def __init__[self]:
self._x = None
@property
def x[self]:
return self._x
@x.setter
def x[self, value]:
self._x = value
@x.deleter
def x[self]:
del self._x
6 đã bị phản đối trong tám năm, kể từ Python 2.3. Không sử dụng nó. Việc bạn sử dụng class C[object]:
def __init__[self]:
self._x = None
@property
def x[self]:
return self._x
@x.setter
def x[self, value]:
self._x = value
@x.deleter
def x[self]:
del self._x
7 cũng trái với Zen of Python - rõ ràng là tốt hơn tiềm ẩn. Nếu bạn thực sự thích vết lõm tăng lên, không cần phải tạo ra một đối tượng vứt bỏ, chỉ cần làm
Nếu lớp con biết thuộc tính được xác định ở đâu, chỉ cần làm:
class A[object]:
def __init__[self]:
self.foo = 8
@apply
def foo[]:
"""A foobar"""
def fget[self]:
return self._foo
def fset[self, val]:
self._foo = val
return property[**locals[]]
class ATimesTwo[A]:
@some_decorator
def foo[]:
def fset[self, val]:
self._foo = val * 2
return something
8class A[object]:
def __init__[self]:
self.foo = 8
@apply
def foo[]:
"""A foobar"""
def fget[self]:
return self._foo
def fset[self, val]:
self._foo = val
return property[**locals[]]
class ATimesTwo[A]:
@some_decorator
def foo[]:
def fset[self, val]:
self._foo = val * 2
return something
9Ví dụ cho một thuộc tính hỗ trợ nối thêm các phương thức cho các chức năng đã đặt:
Việc sử dụng giống như đối với các thuộc tính bình thường, chỉ bây giờ có thể thêm các phương thức vào các setters thuộc tính:
Gợi ý: 2
>>> a = A[]
>>> a.foo
8
>>> b = ATimesTwo[]
>>> b.foo
16
0Chỉ ghi đè một getter, setter hoặc một đối tượng thuộc tính, chỉ ghi đè lên một getter, setter hoặc một dấu hiệu của một đối tượng thuộc tính, bắt đầu với ngôn ngữ Python, bắt đầu với ngôn ngữ Python
>>> a = A[]
>>> a.foo
8
>>> b = ATimesTwo[]
>>> b.foo
16
1Lưu ý: Các biến riêng tư không thực sự tồn tại trong Python. Đơn giản là có các tiêu chuẩn để được tuân theo. Bản thân ngôn ngữ không áp dụng bất kỳ hạn chế nào.: The private variables don't actually exist in Python. There are simply norms to be followed. The language itself doesn't apply any restrictions.
>>> a = A[]
>>> a.foo
8
>>> b = ATimesTwo[]
>>> b.foo
16
2