Đây là thứ tôi đã nghĩ ra, sẽ hoạt động chính xác như phương pháp tồn tại.
Đầu tiên chúng ta hãy thiết lập một điều: Bạn không thể phân biệt trong __getattr__
nếu attr
xuất phát từ một cuộc gọi hàm hoặc một "truy cập thuộc tính", bởi vì một phương pháp học là một thuộc tính của lớp học của bạn.Vì vậy, ai đó có thể truy cập vào phương pháp mà ngay cả khi họ không có ý định gọi nó, như trong:
class Test:
def method(self):
print "Hi, I am method"
>> t = Test()
>> t.method # just access the method "as an attribute"
<bound method Test.method of <__main__.Test instance at 0x10a970c68>>
>> t.method() # actually call the method
Hi, I am method
Chính vì vậy, điều gần gũi nhất tôi có thể nghĩ đến là hành vi này:
Tạo một lớp Một, chẳng hạn rằng:
- Khi chúng tôi cố gắng truy cập thuộc tính/phương pháp đã tồn tại trong lớp đó, hoạt động bình thường và chỉ trả về thuộc tính/phương thức được yêu cầu.
- Khi chúng tôi cố gắng truy cập nội dung không tồn tại trong định nghĩa lớp, hãy coi đó là phương thức lớp và có 1 trình xử lý chung cho tất cả các phương pháp như vậy.
Trước tiên tôi sẽ viết định nghĩa lớp và sau đó cho biết cách truy cập một phương thức không tồn tại giống như truy cập vào phương thức tồn tại, cho dù bạn đang truy cập hoặc thực sự gọi nó.
định nghĩa Class:
class A(object):
def __init__(self):
self.x = 1 # set some attribute
def __getattr__(self,attr):
try:
return super(A, self).__getattr__(attr)
except AttributeError:
return self.__get_global_handler(attr)
def __get_global_handler(self, name):
# Do anything that you need to do before simulating the method call
handler = self.__global_handler
handler.im_func.func_name = name # Change the method's name
return handler
def __global_handler(self, *args, **kwargs):
# Do something with these arguments
print "I am an imaginary method with name %s" % self.__global_handler.im_func.func_name
print "My arguments are: " + str(args)
print "My keyword arguments are: " + str(kwargs)
def real_method(self, *args, **kwargs):
print "I am a method that you actually defined"
print "My name is %s" % self.real_method.im_func.func_name
print "My arguments are: " + str(args)
print "My keyword arguments are: " + str(kwargs)
tôi đã thêm các phương pháp real_method
chỉ vì vậy tôi có cái gì đó thực sự tồn tại trong lớp để so sánh hành vi của nó với điều đó của một 'phương pháp tưởng tượng'
Dưới đây là kết quả:
>> a = A()
>> # First let's try simple access (no method call)
>> a.real_method # The method that is actually defined in the class
<bound method A.real_method of <test.A object at 0x10a9784d0>>
>> a.imaginary_method # Some method that is not defined
<bound method A.imaginary_method of <test.A object at 0x10a9784d0>>
>> # Now let's try to call each of these methods
>> a.real_method(1, 2, x=3, y=4)
I am a method that you actually defined
My name is real_method
My arguments are: (1, 2)
My keyword arguments are: {'y': 4, 'x': 3}
>> a.imaginary_method(1, 2, x=3, y=4)
I am an imaginary method with name imaginary_method
My arguments are: (1, 2)
My keyword arguments are: {'y': 4, 'x': 3}
>> # Now let's try to access the x attribute, just to make sure that 'regular' attribute access works fine as well
>> a.x
1
Phương thức được xử lý không khác với bất kỳ thuộc tính nào khác, bạn vẫn cần '__getattr__' /' __getattribute__'. – jonrsharpe
@jonrsharpe mmh nếu tôi thực hiện một lớp A với '__getattr__' và một bản in bên trong và làm' a = A(); a.foo' nó sẽ in 'foo' nhưng nếu tôi gọi' a = A(); a.foo() 'nó sẽ tăng một đối tượng' TypeError: 'NoneType' không được gọi là ' – Salo
'__getattr__' sẽ vẫn phải * return * một cái gì đó có thể gọi được, không * gọi * nó, nếu không bạn sẽ nhận được' None' mặc định – jonrsharpe