Pra*_*ota 11 python oop methods self
考虑一下Python中策略模式的这个例子(改编自这里的例子).在这种情况下,替代策略是一种功能.
class StrategyExample(object):
def __init__(self, strategy=None) :
if strategy:
self.execute = strategy
def execute(*args):
# I know that the first argument for a method
# must be 'self'. This is just for the sake of
# demonstration
print locals()
#alternate strategy is a function
def alt_strategy(*args):
print locals()
Run Code Online (Sandbox Code Playgroud)
以下是默认策略的结果.
>>> s0 = StrategyExample()
>>> print s0
<__main__.StrategyExample object at 0x100460d90>
>>> s0.execute()
{'args': (<__main__.StrategyExample object at 0x100460d90>,)}
Run Code Online (Sandbox Code Playgroud)
在上面的例子中s0.execute
是一个方法(不是普通的vanilla函数),因此args
,正如预期的那样,第一个参数是self
.
以下是替代策略的结果.
>>> s1 = StrategyExample(alt_strategy)
>>> s1.execute()
{'args': ()}
Run Code Online (Sandbox Code Playgroud)
在这种情况下s1.execute
是普通的香草功能,并按预期,不接收self
.因此args
是空的.等一下!这怎么发生的?
方法和函数都以相同的方式调用.方法如何自动self
作为第一个参数?当一个方法被一个普通的vanilla函数替换时,它怎么没有得到self
第一个参数?
我能够找到的唯一区别是我检查了默认策略和备用策略的属性.
>>> print dir(s0.execute)
['__cmp__', '__func__', '__self__', ...]
>>> print dir(s1.execute)
# does not have __self__ attribute
Run Code Online (Sandbox Code Playgroud)
__self__
属性s0.execute
(方法)的存在,但缺乏它s1.execute
(函数)会以某种方式解释这种行为差异吗?这一切在内部如何运作?
您需要将未绑定的方法(即带self
参数)分配给类或绑定到对象的方法.
通过描述符机制,您可以创建自己的绑定方法,这也是将(未绑定)函数分配给类时的原因:
my_instance = MyClass()
MyClass.my_method = my_method
Run Code Online (Sandbox Code Playgroud)
在调用时my_instance.my_method()
,查找将不会找到条目my_instance
,这就是为什么它稍后将最终执行此操作:MyClass.my_method.__get__(my_instance, MyClass)
- 这是描述符协议.这将返回一个绑定到my_instance的新方法,然后使用()
该属性后面的运算符执行该方法.
这将在MyClass的所有实例之间共享方法,无论它们何时被创建.但是,在分配该属性之前,他们可以"隐藏"该方法.
如果您只希望特定对象具有该方法,则只需手动创建绑定方法:
my_instance.my_method = my_method.__get__(my_instance, MyClass)
Run Code Online (Sandbox Code Playgroud)
有关描述符(指南)的更多详细信息,请参见此处.
你可以阅读完整的说明这里的蟒蛇参考,在“用户定义的方法”。可以在python教程的方法对象说明中找到更简短的说明:
如果您仍然不了解方法的工作方式,那么看一下实现也许可以澄清问题。当引用的实例属性不是数据属性时,将搜索其类。如果名称表示作为函数对象的有效类属性,则通过将实例对象和刚在抽象对象中一起找到的函数对象打包(指向)来创建方法对象:这是方法对象。当使用实参列表调用方法对象时,将从实例对象和实参列表构造一个新的实参列表,并使用该新的实参列表来调用函数对象。
基本上,您的示例中发生的是:
StrategyExample.execute
您将获得一个“未绑定方法”:它不“知道”该实例“属于”哪个实例,因此,如果要在实例上使用它,则需要自己提供实例作为第一个参数。StrategyExample.execute(s0)
self.execute
或s0.execute
,您将获得一个“绑定方法”:它“知道”它“属于”哪个对象,并将以该实例作为第一个参数被调用。self.execute = strategy
甚至s0.execute = strategy
是……只是一个普通函数(与方法相反,它不会通过类传递)为了使您的示例在两种情况下均能正常工作:
您可以将函数转换为“真实”方法:可以使用types.MethodType
以下方法进行操作:
self.execute = types.MethodType(strategy, self, StrategyExample)
Run Code Online (Sandbox Code Playgroud)
(您或多或少告诉类,当execute
要求该特定实例时,它应该变成strategy
绑定方法)
或-如果您的策略确实不需要访问该实例-您可以采用另一种方法,将原始execute
方法转换为静态方法(再次使其成为普通函数:将不会以实例作为第一个调用该方法参数,因此s0.execute()
与StrategyExample.execute()
)完全相同:
@staticmethod
def execute(*args):
print locals()
Run Code Online (Sandbox Code Playgroud) 归档时间: |
|
查看次数: |
2131 次 |
最近记录: |