2011-09-10 26 views
6

Người ta có thể làm điều gì đó như thế này:Sử dụng cùng một chức năng như ví dụ và classmethod trong python

class master: 
    @combomethod 
    def foo(param): 
     param.bar() # Param could be type as well as object 

class slaveClass(master): 
    @classmethod 
    def bar(cls): 
     print("This is class method") 

slaveType = slaveClass 
slaveType.foo() 

class slaveInstance(master): 
    def __init__(self, data): 
     self.data = data 
    def bar(self): 
     print("This is "+self.data+" method") 


slaveType = slaveInstance("instance") 
slaveType.foo() 

combomethod được định nghĩa trong "Creating a method that is simultaneously an instance and class method".

Câu hỏi của tôi là, tại sao nó như thế này, thông số đầu tiên mặc định không thể được sử dụng làm thông số của comboclass. Hoặc ít nhất, tại sao tôi không thể vượt qua đối tượng để classmethod như tham số đầu tiên. Tôi biết whats sự khác biệt giữa classmethod và instancemethods và những gì là trang trí, nhưng tôi có thể không hiểu, làm thế nào được xây dựng trong @classmethod và thông qua self thông qua được thực hiện. Có chỉ là một số hạn chế kỹ thuật? Hoặc tại sao không phải là combomethod allready được tích hợp sẵn?

+2

Vui lòng không sử dụng chữ viết ("smth") trong các bài đăng SO. –

+0

Tôi không thể làm cho người đứng đầu cũng không đuôi của những gì bạn đang yêu cầu ở đây ... –

+0

@Ignacio Tôi muốn biết nếu tôi làm tất cả sai và có cách đơn giản hơn? Tôi nghĩ rằng có thể có một số cách xây dựng để làm điều tương tự và nếu không, tại sao không? – Johu

Trả lời

3

combomethod không tạo đối tượng phương thức khi được truy cập nhưng có chức năng được bao bọc đặc biệt. Giống như các phương thức, mỗi truy cập tạo một đối tượng mới, trong trường hợp này là một đối tượng hàm mới.

class A: 
    def __init__(self): 
     self.data = 'instance' 

    @combomethod 
    def foo(param): 
     if isinstance(param, A): 
      print("This is an " + param.data + " method.") 
     elif param is A: 
      print("This is a class method.") 

>>> a = A() 
>>> A.foo 
<function foo at 0x00CFE810> 
>>> a.foo 
<function foo at 0x00CFE858> 

>>> A.foo() 
This is a class method. 
>>> a.foo() 
This is an instance method. 

Đó là mới cho mỗi truy cập:

>>> A.foo is A.foo 
False 
>>> a.foo is a.foo 
False 

foo thực sự _wrapper là trong ngụy trang:

>>> A.foo.__code__.co_name 
'_wrapper' 

Khi gọi từ một lớp học đóng cửa có obj == None (lưu ý rằng ' self 'ở đây đề cập đến combomethod, có tham chiếu đến đối tượng hàm ban đầu trong self.method):

>>> print(*zip(A.foo.__code__.co_freevars, A.foo.__closure__), sep='\n') 
('obj', <cell at 0x011983F0: NoneType object at 0x1E1DF8F4>) 
('self', <cell at 0x01198530: combomethod object at 0x00D29630>) 
('objtype', <cell at 0x00D29D10: type object at 0x01196858>) 

Khi được gọi là thuộc tính của một thể hiện, obj là dụ:

>>> print(*zip(a.foo.__code__.co_freevars, a.foo.__closure__), sep='\n') 
('obj', <cell at 0x01198570: A object at 0x00D29FD0>) 
('self', <cell at 0x01198530: combomethod object at 0x00D29630>) 
('objtype', <cell at 0x00D29D10: type object at 0x01196858>) 

Dưới đây là chức năng gốc được lưu trữ trong combomethod:

>>> A.foo.__closure__[1].cell_contents.method 
<function foo at 0x00D1CB70> 
>>> A.foo.__closure__[1].cell_contents.method.__code__.co_name 
'foo' 

_wrapper thực hiện self.method với một trong hai lớp hoặc ví dụ làm đối số đầu tiên cho giá trị của obj:

if obj is not None: 
    return self.method(obj, *args, **kwargs) 
else: 
    return self.method(objtype, *args, **kwargs) 
+0

Vì vậy, bạn đã nói với tôi làm thế nào combomethod làm việc và tôi hiểu hầu hết của nó. Cảm ơn bạn đã nỗ lực của bạn! Bạn cũng có thể cho tôi biết, tại sao nó xấu và nó có thể được thực hiện trong bất kỳ cách nào tốt hơn? Wrapper xung quanh chức năng làm cho nó bộ nhớ không hiệu quả? – Johu

9

sử dụng điều này:

class A(object): 

    @classmethod 
    def print(cls): 
     print 'A' 

    def __print(self): 
     print 'B' 

    def __init__(self): 
     self.print = self.__print 


a = A() 
a.print() 
A.print() 
Các vấn đề liên quan