Tôi đang gặp khó khăn khi hiểu những gì sẽ xảy ra khi tôi cố gắng lồng ghép các bộ mô tả/trang trí. Tôi đang sử dụng python 2.7.Các bộ mô tả/trang trí làm tổ trong python
Ví dụ, chúng ta hãy phiên bản đơn giản sau đây của property
và classmethod
:
class MyProperty(object):
def __init__(self, fget):
self.fget = fget
def __get__(self, obj, objtype=None):
print 'IN MyProperty.__get__'
return self.fget(obj)
class MyClassMethod(object):
def __init__(self, f):
self.f = f
def __get__(self, obj, objtype=None):
print 'IN MyClassMethod.__get__'
def f(*args, **kwargs):
return self.f(objtype, *args, **kwargs)
return f
Đang cố gắng để tổ họ:
class A(object):
# doesn't work:
@MyProperty
@MyClassMethod
def klsproperty(cls):
return 555
# works:
@MyProperty
def prop(self):
return 111
# works:
@MyClassMethod
def klsmethod(cls, x):
return x**2
% print A.klsproperty
IN MyProperty.__get__
...
TypeError: 'MyClassMethod' object is not callable
Phương pháp __get__
của bộ mô tả nội MyClassMethod
không nhận được gọi là. Không hiểu tại sao, tôi đã cố gắng ném trong (những gì tôi nghĩ là) một mô tả không-op:
class NoopDescriptor(object):
def __init__(self, f):
self.f = f
def __get__(self, obj, objtype=None):
print 'IN NoopDescriptor.__get__'
return self.f.__get__(obj, objtype=objtype)
Cố gắng sử dụng các không-op mô tả/trang trí trong tổ:
class B(object):
# works:
@NoopDescriptor
@MyProperty
def prop1(self):
return 888
# doesn't work:
@MyProperty
@NoopDescriptor
def prop2(self):
return 999
% print B().prop1
IN NoopDescriptor.__get__
IN MyProperty.__get__
888
% print B().prop2
IN MyProperty.__get__
...
TypeError: 'NoopDescriptor' object is not callable
Tôi không hiểu tại sao B().prop1
hoạt động và B().prop2
thì không.
Câu hỏi:
- Tôi đang làm gì sai? Tại sao tôi gặp lỗi
object is not callable
? - Cách phù hợp là gì? ví dụ. những gì là cách tốt nhất để xác định
MyClassProperty
khi tái sử dụngMyClassMethod
vàMyProperty
(hoặcclassmethod
vàproperty
)
Chìa khóa để hiểu trực giác này là '@ MyProperty' tạo ra thứ gì đó hoạt động giống như thuộc tính _data_, không phải là phương thức, do đó bạn không thể lồng nó bằng bộ mô tả phương thức. Sự hiểu biết trực quan đó chỉ giúp bạn cho đến nay; câu chuyện đầy đủ nằm trong câu trả lời của isedev. – abarnert