Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/362.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
__在Python中获取方法/函数的_Python - Fatal编程技术网

__在Python中获取方法/函数的

__在Python中获取方法/函数的,python,Python,我有一段代码,我正试图理解,即使有现有的答案,我真的无法理解下面代码的目的,有人能帮我理解吗 我已经在这里查看了各种相关问题(\uuu get\uuu()),但我找不到具体的答案。我知道下面的类正在尝试动态创建一个方法(可能我们从一个\uuu getattr\uuuu()方法获得这个类,该方法找不到属性),并将该方法返回给调用方。我已经在需要理解的代码行的正上方进行了注释 class MethodGen(object): def __getattr__(self, name):

我有一段代码,我正试图理解,即使有现有的答案,我真的无法理解下面代码的目的,有人能帮我理解吗

我已经在这里查看了各种相关问题(
\uuu get\uuu()
),但我找不到具体的答案。我知道下面的类正在尝试动态创建一个方法(可能我们从一个
\uuu getattr\uuuu()
方法获得这个类,该方法找不到属性),并将该方法返回给调用方。我已经在需要理解的代码行的正上方进行了注释

class MethodGen(object):

    def __getattr__(self, name):
        method = self.method_gen(name)
        if method:
           return self.method_gen(name)


    def method_gen(self, name):

        def method(*args, **kwargs):
            print("Creating a method here")

        # Below are the two lines of code I need help understanding with
        method.__name__ = name
        setattr(self, name, method.__get__(self))

        return method

如果我没有错的话,
method()
函数的属性
\uuu name\uuu
已经设置好了,但是在
setattr()
函数中,类
MethodGen
name
的属性被设置为什么?

有趣的是,以前从未见过这样做过,似乎很难维护(可能会让其他开发者想绞死你)

我更改了一些代码,以便您可以看到更多正在发生的事情

class MethodGen(object):

    def method_gen(self, name):
        print("Creating a method here")
        def method(*args, **kwargs):
            print("Calling method")
            print(args) # so we can see what is actually being outputted

        # Below are the two lines of code I need help understanding with
        method.__name__ = name # These the method name equal to name (i.e. we can call the method this way) 
        # The following is adding the new method to the current class.
        setattr(self, name, method.__get__(self)) # Adds the method to this class

        # I would do: setattr(self, name, method) though and remove the __get__

        return method # Returns the emthod

m = MethodGen()
test = m.method_gen("my_method") # I created a method in MethodGen class called my_method
test("test") # It returned a pointer to the method that I can use
m.my_method("test") # Or I can now call that method in the class.
m.method_gen("method_2")
m.method_2("test2")

考虑以下类别:

class Foo:
    def bar(self):
        print("hi")

f = Foo()
f.bar()
bar
是一个以函数作为其值的类属性。因为
function
实现了描述符协议,但是,以
Foo.bar
f.bar
访问它并不会立即返回函数本身;它会导致调用函数的
\u get\u
方法,并返回原始函数(如
Foo.bar
)或类型为
instancemethod
(如
f.bar
)的新值。
f.bar()
的计算结果为
Foo.bar.\uu get\uuuu(f,Foo)(

method\u gen
接受名为
method
的函数,并将通过调用该函数的
\uuuu get\uuuu
方法检索到的实际方法附加到一个对象上。其目的是使类似于此的操作生效:

>>> m = MethodGen()
>>> n = MethodGen()
>>> m.foo()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: 'MethodGen' object has no attribute 'foo'
>>> n.foo()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: 'MethodGen' object has no attribute 'foo'
>>> m.method_gen('foo')
<function foo at 0x10465c758>
>>> m.foo()
Creating a method here
>>> n.foo()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: 'MethodGen' object has no attribute 'foo'
>m=MethodGen()
>>>n=MethodGen()
>>>傅先生()
回溯(最近一次呼叫最后一次):
文件“”,第1行,在
AttributeError:“MethodGen”对象没有属性“foo”
>>>n.foo()
回溯(最近一次呼叫最后一次):
文件“”,第1行,在
AttributeError:“MethodGen”对象没有属性“foo”
>>>m.method_gen(“foo”)
>>>傅先生()
在这里创建一个方法
>>>n.foo()
回溯(最近一次呼叫最后一次):
文件“”,第1行,在
AttributeError:“MethodGen”对象没有属性“foo”

最初,
MethodGen
除了
method\u gen
之外没有任何其他方法。您可以在两个实例中的任何一个上尝试调用名为
foo
的方法时看到引发的异常。但是,调用
method\u gen
只会将新方法附加到该特定实例。调用
m.method\u gen>后(“foo”)
m.foo()
调用了
method\u-gen
定义的方法。该调用不会影响
MethodGen
的其他实例,比如
n

这个问题真的让我很感兴趣。提供的两个答案似乎并不能说明全部情况。困扰我的是,在这一行中:

setattr(self, name, method.__get__(self))
代码并不是为了在某个时候调用
方法。
而设置的。相反,
方法。
实际上是被调用的!但是当对象的特定属性(本例中是MethodGen的实例)实际被引用时,是否会调用此
方法阅读文档后,您会得到这样的印象…一个属性链接到一个实现
\uuuuu get\uuuu
的描述符,该实现决定了当引用该属性时返回的内容。但是,这里并不是这样。这一切都发生在这一点之前。那么这里到底发生了什么

答案在于。关键语言是:

为了支持方法调用,函数包括 属性访问期间绑定方法。这意味着所有函数 是非数据描述符,当绑定方法 从对象调用

method.\uuuu get\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuoself)
正是这里所描述的。因此
方法。\u绑定到
self
的函数
。在本例中,
self
MethodGen
的一个实例,因此此调用返回对
方法的引用绑定到
MethodGen
实例的函数
。在这种情况下,
\uuuu get\uuuu
方法与引用属性的行为无关。相反,此调用将函数引用转换为方法引用

现在我们有了一个对我们动态创建的方法的引用。但是当一个具有正确名称的属性在它绑定到的实例上被引用时,我们如何设置它以使它在正确的时间被调用?这就是
setattr(self,name,X)的位置
part进入。此调用接受我们的新方法,并将其绑定到实例上名为
name
的属性

以上所有这些都是原因:

setattr(self, name, method.__get__(self))
正在将新方法添加到
self
,已调用
method\u gen
MethodGen
类的实例

方法.\uuuuu name\uuuuuu=name
部分并不是那么重要。只执行上面讨论的一行代码就可以实现您真正想要的所有行为。这个额外的步骤只是将一个名称附加到我们的新方法上,这样,请求方法名称的代码,就像使用内省编写文档的代码一样,将得到正确的结果t name。是实例属性的名称…传递给
setattr
…的名称真正重要,并且真正“命名”了方法。

因此,
settattr()
函数只是试图使现在新创建的类
MethodGen
的属性正确吗