使用参数和签名

时间:2016-09-21 08:28:51

标签: python python-3.x metaprogramming

我是一个相对较新的Python学习者。所以,在经历不同的编码技术时,我遇到了这个:

from inspect import Parameter, Signature

def make_signature(names):
    return Signature(Parameter(name, Parameter.POSITIONAL_OR_KEYWORD) for name in names)

class Structure:
    list_fields = []
    def __init__(self, *args):
        for name, val in zip(self.list_fields, args):
            setattr(self, name, val)

class Stock(Structure):
    __signature__ = make_signature(['name', 'shares', 'price'])
    #list_fields = ['name', 'shares', 'price'] 

class Point(Structure):
    list_fields = ['x', 'y']

obj2=Point(20,40)
obj1=Stock('googl', 100, 8000)
print(obj1.name)

我理解Structure类及其与继承Point类的Structure类的集成,因此它是__init__方法。但是当我创建Point类的对象时,它不支持位置参数,但Stock类对象确实支持该功能。

  • 任何人都可以向我解释为什么&怎么会这样?
  • 何时使用参数,签名?
  • 这又如何与元编程相关?
  • 更多这样的例子。
  • Parameter方法中make_signature函数的用途以及make_signature方法正在做什么?
  • 程序的流程,即哪个函数返回给谁,反之亦然。据我所知,Stock类和Point类正在调用Structure类,但make_signature方法何时进入?

我试着阅读一些关于Signature的文档,但这些例子不属于这种情况,对我来说太重了,因为我一直在迷失回溯这段代码文件,我也找不到任何好处关于Python中元编程的解释性文档。

1 个答案:

答案 0 :(得分:2)

  

任何人都可以向我解释为什么&怎么会这样?

两个类接受*argsStructure.__init__指示的位置参数:

s = Stock('pos_arg1', 'pos_arg2', 'pos_arg3')
p = Point('pos_arg1', 'pos_arg2', 'pos_arg3')

不同之处在于,Stock实际上并未设置任何参数,因为,由于您已注释掉list_fieldsStructure.__init__将使用Structure.list_fields这是空的。这就是为什么尝试访问name个实例上的Stock会引发AttributeError

在这两种情况下,list_fields 限制可以设置哪些参数。对于上一代码段中的Point个实例,x将等于pos_arg1,而y将等于pos_arg2; pos_arg3基本上是被抛出的。这是由于zip构建了元组,直到其中一个迭代用尽:

for i, j in zip(['x', 'y'], ['pos_arg1', 'pos_arg2', 'pos_arg3']):
    print(i, j)

打印:

x pos_arg1
y pos_arg2

当提供空列表时,它甚至不循环。这是初始化Stock时发生的情况,使用Structure.list_fields = []

for i, j in zip([], ['pos_arg1', 'pos_arg2', 'pos_arg3']):
    print(i, j)

不打印任何内容,因此不会调用setattr

  

何时使用参数,签名?

当您想要支持对类的进一步内省时(或者在一般情况下为callables),您可以在类中添加__signature__属性(与Stock一样)并将其选中像inspect.signature这样的工具,即:

inspect.signature(Stock)
Out[16]: <Signature (name, shares, price)>

inspect.signature(Point)
Out[17]: <Signature (*args)>

签名尝试查看对象是否具有object.__signature__,如果是,则在调用时构造签名的表示。

此外,您可以bind签名自己并使其支持POSITIONAL_OR_KEYWORD参数。

一般情况下,这只会在很少的情况下出现。简而言之:你会知道你是否需要它。

  

这又如何与元编程相关?

此具体示例无关。您可以使用元编程来增强它,您将在我将链接的演示文稿中看到。

  

还有更多这样的例子。

这太宽泛了。但你的例子来自david beazly的元编程演示,here's the presentation

  

据我所知,Stock函数和Point函数调用的是Structure类,但make_signature方法在哪里?

StockPoint都使用Structure.__init__,它将使用list_fields中定义的属性填充实例字典。

__signature__ = make_signature([...])在创建类时执行 ,Python在遇到它时执行class的主体。 make_signature将被调用并创建一个Signature对象,并且将对__signature__进行分配。