我需要将类方法存储到列表中并通过循环执行它们。我定义了一个装饰器并使用它将类方法附加到列表中。该类在一个单独的模块中定义,并在主I循环中通过列表定义并调用存储在该列表中的类方法。当我运行main时,我收到错误:
TypeError:example_01()缺少1个必需的位置参数:' self'
我知道我需要创建一个类Bar实例来执行它的方法,但这会阻止我使用该列表。什么是使用这种结构的正确方法? 请帮忙......
我正在使用python 3.4
由于
mybar.py
========
examples = list()
def example(fn):
try: name = 'Example %d' % int(fn.__name__[7:])
except: name = fn.__name__
def wrapped():
print('Running: %s\n' % name)
fn()
print('\n')
examples.append(wrapped)
return wrapped
class Bar:
def __init__(self):
self.message = "I'm %s" % (__name__)
@example
def example_01(self):
print(self.message)
print("Executing example_01")
@example
def example_02(selfs):
print(self.message)
print("Executing example_02")
main.py
=======
from bar import mybar
def main():
for example in mybar.examples:
example()
if __name__ == "__main__":
main()
我修改了我的代码,为每个类方法使用@classmethod装饰器,但是它有效,但我不明白为什么。我不必用Bar明确调用example()。也没有像python doc中记载的那样将类对象提供给类函数的参数,例如def example_01(cls)。请有人解释一下
mybar.py
=======
class Bar:
data = 25
def __init__(self):
self.message = "I'm %s" % (__name__)
Bar.data = 30
@classmethod
@example
def example_01():
print("Executing example_01")
print("Data: ", Bar.data)
@classmethod
@example
def example_02():
print("Executing example_02")
print("Data: ", Bar.data)
Running: example_01
Executing example_01
Data: 25
Running: example_02
Executing example_02
Data: 25
答案 0 :(得分:1)
在Python中,函数(采用简单的参数列表)和方法(采用参数加上特殊的self
或cls
参数)之间存在区别。一旦将函数分配给类名称空间内的变量,该函数就成为一种方法。
在装饰函数example_01
和example_02
的时候,它们实际上不是方法而是普通函数。这些函数将附加到examples
,因此不会调用生成的类方法。
你无法轻松解决这个问题。你首先用@example
装饰(然后你还没有类方法),或者先用@classmethod
装饰(然后你所拥有的只是一个不是类方法的中间对象) 。获取最终类方法的唯一方法是在分配之后从类中检索方法,这显然不能从装饰器中完成。
最简单的方法是完全删除装饰器并以简单的方式将类方法分配给examples
:
examples = [Bar.example_01, Bar.example_02]
如果你真的想使用一个装饰器,你可以在examples
中放一个包装器,它使用getattr
从类中检索类方法并返回未修改的 function fn
。
请注意,由于message
变量是在类Bar
的构造函数中设置的,因此您需要一个Bar
实例来访问它。如果要在不创建虚拟实例的情况下从类方法访问变量,则必须在类名称空间中进行设置。但是,__name__
变量没有在那里设置,所以你基本上不能像你想要的那样使用message
变量。此外,在类方法中,第一个参数是类本身(通常称为cls
),而不是self
(实例),以及以{{1}结尾的print
语句导致双线中断。
这是最终代码的样子:
\n
答案 1 :(得分:0)
如果您不想使用装饰器,则可以检索类的方法列表,并使用方法__getattribute __()从类的实例调用每个方法。这是代码:
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<system.webServer>
<httpProtocol>
<customHeaders>
<add name="Access-Control-Allow-Origin" value="*" />
</customHeaders>
</httpProtocol>
</system.webServer>
</configuration>