Python方法对象创建

2024-09-24 22:28:28 发布

您现在位置:Python中文网/ 问答频道 /正文

Python的类实例对象属性。那些属性可以是数据属性或方法。你知道吗

我们以这门课为例

class Foo:

    def bar(self):
        print("FooBar")

让我们创建一个类实例

fooInstance = Foo()

当我从文件中读到并亲自测试时,我意识到 每次在代码中引用或每次从实例中调用bar时

fooInstance.bar

每次都在内部创建一个方法对象。你知道吗

我的问题是为什么不缓存和重用它

我的一个假设是,method对象的可调用对象可能以某种方式在内部更改地址(例如,由于重新分配?)指向它的指针可能会失效。你知道吗

抱歉,如果这个问题是“愚蠢的”,我是一个全新的Python,所以我对它的知识是很少的,更不用说它的内部。你知道吗


Tags: 数据对象实例方法代码self属性foo
2条回答

Python函数是descriptors。您可以通过查看dir来检查这一点:

>>> def fn(self):
...     pass
... 
>>> dir(fn)
['__call__', '__class__', '__closure__', '__code__', '__defaults__', '__delattr__', '__dict__', '__doc__', '__format__', '__get__', '__getattribute__', '__globals__', '__hash__', '__init__', '__module__', '__name__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', 'func_closure', 'func_code', 'func_defaults', 'func_dict', 'func_doc', 'func_globals', 'func_name']
>>> fn.__get__
<method-wrapper '__get__' of function object at 0x7fa5585550c8>

注意^{} method。我们可以使用它来生成绑定方法:

>>> class Bar(object): pass
... 
>>> b = Bar()
>>> fn.__get__(b, Bar)
<bound method Bar.fn of <__main__.Bar object at 0x7fa5585cdcd0>>

事实上,这就是python在访问作为函数的类的属性时自动为您做的事情。你知道吗

现在,关于缓存函数的问题,可以从任何地方将其放到类中。我可以向任何类添加绑定方法,就像我在上面所做的简单赋值b.fn = fn.__get__(b, Bar),现在实例b有一个绑定方法fn,即使Bar的其他实例都没有该方法。我可以为多个班级做这个。如果描述符要缓存这些值,则需要保留一个查找实例和类的查找表,以查看是否已经为该实例和类创建了绑定方法。下面是一个简单的例子:

def fn(self):
    return self

class A(object):
    fn = fn

class B(object):
    fn = fn

注意,AB持有对同一函数的引用,当在实例上访问该属性时,它们都会根据需要生成绑定方法。你知道吗

首先构造查找表是有问题的,因为self可能不可散列。我认为这可能是每次创建新实例的主要原因。即使不是这样,查找表也需要存储weakrefs而不是实际引用,以便在必要时可以对整个内容进行垃圾收集。我猜在使用weakrefs时,创建一个新的绑定方法可能几乎和执行查找和解析一样快。你知道吗

你所拥有的只是一个没有参数的方法,每次你调用一个它将执行的方法。一个方法变量将把这个方法赋给其他的方法,以便以后调用它。你知道吗

如果您有一个带计数器的变量,并且每次可以打印出来并查看它是如何被修改的,您都会向该方法添加一个。你知道吗

相关问题 更多 >