我是一个相对较新的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中元编程的解释性文档。
答案 0 :(得分:2)
任何人都可以向我解释为什么&怎么会这样?
两个类仅接受*args
中Structure.__init__
指示的位置参数:
s = Stock('pos_arg1', 'pos_arg2', 'pos_arg3')
p = Point('pos_arg1', 'pos_arg2', 'pos_arg3')
不同之处在于,Stock
实际上并未设置任何参数,因为,由于您已注释掉list_fields
,Structure.__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方法在哪里?
Stock
和Point
都使用Structure.__init__
,它将使用list_fields
中定义的属性填充实例字典。
__signature__ = make_signature([...])
在创建类时执行 ,Python在遇到它时执行class
的主体。 make_signature
将被调用并创建一个Signature
对象,并且将对__signature__
进行分配。