python方法窃取器
如何从一个类“窃取”或将方法复制到另一个类上 示例代码:python方法窃取器,python,oop,Python,Oop,如何从一个类“窃取”或将方法复制到另一个类上 示例代码: class A(object): def foo(self): print "blah" class B(object): foo = A.foo B().foo() 预期产出: "blah" 相反: TypeError:必须使用以下实例调用未绑定的方法foo() 第一个参数(没有得到任何结果) 你可以在这里用。继承允许您基于另一个对象创建对象,继承其所有函数和属性 在本例中,它看起来像: class A(obj
class A(object):
def foo(self):
print "blah"
class B(object):
foo = A.foo
B().foo()
预期产出:
"blah"
相反:
TypeError:必须使用以下实例调用未绑定的方法foo()
第一个参数(没有得到任何结果)
你可以在这里用。继承允许您基于另一个对象创建对象,继承其所有函数和属性
在本例中,它看起来像:
class A(object):
def foo(self):
print "blah"
class B(A):
# You can add new methods or attributes here,
# or even overwrite those inherited from A if you
# really want to, though you have to be careful with that.
pass
在该声明之后
>>> B().foo()
"blah"
这是因为:
- 您创建了类
,并为其创建了方法A
foo
- 您创建了类
继承自B
,这意味着当A
生下它时,A
与B
所拥有的一切一起诞生。A
- 在我们的例子中,
是B
的精确副本,因为我们没有对它做任何其他操作。但是,我们可以进行更改或添加更多方法A
- 在我们的例子中,
class A(object):
def foo(self):
print "blah"
class B(A):
def newfoo(self):
print "class A can't do this!"
在使用中,我们会看到:
>>> A().foo()
blah
>>> B().foo()
blah
>>> A().newfoo()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: 'A' object has no attribute 'newfoo'
>>> B().newfoo()
class A can't do this!
而不是
class B(object):
foo = A().foo
当您在没有
()
的情况下编写A.foo
时,您直接从A
类型请求方法,这在Python中不起作用。如果要执行foo=A().foo
,您要做的是实例化A
对象,然后获取其方法的副本foo
,然后分配它 使用\uuuu func\uuu
:
>>> A.foo
<unbound method A.foo>
>>> A.foo.__func__
<function foo at 0x00BC5F70>
>>> class B(object):
... foo = A.foo.__func__
...
>>> B().foo()
"blah"
>A.foo
>>>A.foo.\u func__
>>>B类(对象):
... foo=A.foo.\uu func__
...
>>>B().foo()
“废话”
引述:
实例方法对象组合了类、类实例和任何可调用对象(通常是用户定义的函数)
特殊只读属性:_self__;为类实例对象,_func__;为函数对象__doc是方法的文档(与函数相同)__名称是方法名称(与函数名称相同)__module_uu是在其中定义方法的模块的名称,如果不可用,则为None
这里的问题是,您试图窃取的是绑定方法,但是,您的示例不涉及使用实例状态(
self
)的函数。因此,您有两个即时选项:
A.foo
的定义设为静态方法(@staticmethod
decorator)functools
a.foo
)需要一个绑定实例参数(self
,其中self是a
的实例)。在正常使用中,第一个参数会自动传递:
a = A()
现在:
…两者都是等价的。在第一种情况下,语法instance.bound_method()
从词汇角度推断InstanceClass.bound_method(instance)
(instance
解析为self
)。这就是调用A.foo()
将导致错误的原因,因为它需要A
的实例
上面的解决方案是将函数扭曲成一个将
None
作为实例传递的函数,因为无论如何都不会使用实例(没有基于状态的逻辑)。在使用staticmethod的情况下,它删除了第一个隐含的预期绑定实例参数self
,因为未绑定的方法已被删除(参见Guido van Rossum的)
但是请注意,unbound方法是一个函数包装器,用于隐式检查第一个传递的参数是否是定义该方法的类的实例,这是该方法的一个先决条件,通常不应违反该先决条件。错误消息为您提供了正确的解决方案,即继承:
B(A)类:
通过
一般来说,您不应该从非基类窃取方法,因为它将中断非基类中的super()
调用(简称super(\uuuu class\uuuuu,self)
)。事实上,该计划:
A类(对象):
def foo(self):
打印“废话”
super()。\uuuu init\uuuuu()
B类(对象):
foo=A.foo.\uu func__
B().foo()
提出:
TypeError: super(type, obj): obj must be an instance or subtype of type
这是因为
super(\uuuuu class\uuuuuu,self)
首先检查self
是否是\uuuuu class\uuuuuuuu
的实例(或子类型),即A
。但是您传递了一个B
实例,并且B
不是a
的子类。因此Python2 unbound方法的错误消息是有用的。如果foo
是类方法而不是实例方法,这将更有意义。或者,他也可以只做a().foo
而不是a.foo.\uu func\ucode>@jdotjdota()。foo
是一个“绑定方法”,绑定到A
的特定实例。在(可能是简化的)示例中,这并不重要,因为它不使用self
,也可以用静态/类方法代替,但在更复杂的场景中它会。我假设OP的意图,尽管没有说明,是从任意类中选择一个有用的方法(也就是说,不打算从中继承,也不是混入),并在他自己的类中拥有相同的方法,但引用/操作他的类的实例,而不是原始类的实例。你是对的。我在考虑这个具体的例子,因为不需要self
,但你肯定是对的,在一般情况下,A().foo
不是一个好的调用。
a = A()
a.foo()
A.foo(a)
TypeError: super(type, obj): obj must be an instance or subtype of type