我有
class Foo():
function bar():
pass
function foobar():
pass
与其按以下方式逐个执行每个函数:
x = Foo()
x.bar()
x.foobar()
是否有一种内置的方法可以循环遍历并按照它们在类中编写的顺序执行每个函数?
我有
class Foo():
function bar():
pass
function foobar():
pass
与其按以下方式逐个执行每个函数:
x = Foo()
x.bar()
x.foobar()
是否有一种内置的方法可以循环遍历并按照它们在类中编写的顺序执行每个函数?
def assignOrder(order):
@decorator
def do_assignment(to_func):
to_func.order = order
return to_func
return do_assignment
class Foo():
@assignOrder(1)
def bar(self):
print "bar"
@assignOrder(2)
def foo(self):
print "foo"
#don't decorate functions you don't want called
def __init__(self):
#don't call this one either!
self.egg = 2
x = Foo()
functions = sorted(
#get a list of fields that have the order set
[
getattr(x, field) for field in dir(x)
if hasattr(getattr(x, field), "order")
],
#sort them by their order
key = (lambda field: field.order)
)
for func in functions:
func()
上面有趣的@assignOrder(1)
行触发了以下操作:def bar(self)
Foo.bar = assignOrder(1)(Foo.bar)
assignOrder(1)
返回一个函数,该函数接受另一个函数作为参数,对其进行更改(添加字段order
并将其设置为1
),然后返回更改后的函数。然后在所装饰的函数上调用此函数(其order
字段被设置),结果替换了原始函数。
这是一种更加高级、易读和易于维护的方式,相当于说:
def bar(self):
print "bar"
Foo.bar.order = 1
不可以。你可以访问 Foo.__dict__
,并依次调用每个值(对于不可调用的成员要捕获错误),但顺序不会保留。
for callable in Foo.__dict__.values():
try:
callable()
except TypeError:
pass
这假设所有函数都不带参数,就像你的例子一样。由于Python将类的方法(和其他属性)存储在字典中,而字典是基本无序的,因此这是不可能的。
如果您不关心顺序,请使用类的__dict__
:
x = Foo()
results = []
for name, method in Foo.__dict__.iteritems():
if callable(method):
results.append(method(x))
这可能是最短的方法之一(类名为C):
for func in filter(lambda x: callable(x), C.__dict__.values()):
pass # here func is the next function, you can execute it here
< p > filter 表达式返回类 C 的所有函数。< /p >
< p > 或者一行代码: < /p >
[func() for func in filter(lambda x: callable(x), C.__dict__.values())]
c = C(); [f(c,*arg) for f in C.__dict__.values() if callable(f)]
- Leon Chang# The custom dictionary
class member_table(dict):
def __init__(self):
self.member_names = []
def __setitem__(self, key, value):
# if the key is not already defined, add to the
# list of keys.
if key not in self:
self.member_names.append(key)
# Call superclass
dict.__setitem__(self, key, value)
# The metaclass
class OrderedClass(type):
# The prepare function
@classmethod
def __prepare__(metacls, name, bases): # No keywords in this case
return member_table()
# The metaclass invocation
def __new__(cls, name, bases, classdict):
# Note that we replace the classdict with a regular
# dict before passing it to the superclass, so that we
# don't continue to record member names after the class
# has been created.
result = type.__new__(cls, name, bases, dict(classdict))
result.member_names = classdict.member_names
return result
class MyClass(metaclass=OrderedClass):
# method1 goes in array element 0
def method1(self):
pass
# method2 goes in array element 1
def method2(self):
pass
x = MyClass()
print([name for name in x.member_names if hasattr(getattr(x, name), '__call__')])
这个代码可以正常运行并保持顺序:
class F:
def f1(self, a):
return (a * 1)
def f2(self, a):
return (a * 2)
def f3(self, a):
return (a * 3)
allFuncs = [f1, f2, f3]
def main():
myF = F()
a = 10
for f in myF.allFuncs:
print('{0}--> {1}'.format(a, f(myF, a)))
输出将会是:
10--> 10
10--> 20
10--> 30
注意:使用这个而不是F.__dict__.values()
的优点在于,你可以列出那些你更喜欢调用的函数列表,而不一定是全部。
我遇到了一个与您相关的问题,但可能会对其他人有帮助,因为我也遇到了同样的情况。
我试过的:
我正在学习 Python 的 datetime
模块,并创建了一个该模块的对象。现在,要从该对象中获取详细信息,我需要手动按 Tab 键,获取可用方法/属性列表,然后输入它们,最后获得结果。而且需要重复多次!
我需要的是:
由于存在可调用的方法(Methods)和不可调用的属性(Attribute),我需要自动化所有这些内容,以便在单个循环中使用或调用它们并查看其结果。
我尝试的是:
我只是制作了一个简单的 for 循环,它遍历 dir(datetimeobj)
…让我向您展示如何做到这一点...
# Creating an Obj
date = datetime.datetime(2020,1,29,12,5)
# Printing (But won't work, discussing 'why' in a bit)
for method in dir(date):
if callable(method):
print(f"{method}() --> {date.method()}")
else:
print(f"{method} --> {date.method}")
看起来没问题,对吧!它应该可以运行……但是,不行——不会成功。
##错误:‘datetime.datetime’对象没有属性‘method’
method
,因此date.method()
/ date.method
是无效的。dir_without_dunders = [method for method in dir(date) if not method.startswith('_')]
for method in dir_without_dunders:
RealMethod = eval(f'date.{method}')
try:
if callable(RealMethod):
print(f"{method}() --> {RealMethod()}")
else:
print(f"{method} --> {RealMethod}")
except:
continue
代码摘要:
• 为您创建了dir_without_dunders
,以便您知道...
• 取了另一个变量RealMethod
,因为method
将具有字符串(名称),只是为了使打印更清晰和合理
• 主要解决方案是使用eval(f'date.{method}')
这就是hack的方法。
• 为什么使用try
块?-因为并非所有方法都可以在没有任何参数的情况下调用,它们需要不同的参数集和数量,因此我只调用了那些可以简单调用的方法!
就是这样。 适用于此日期时间对象调用,因为它具有大多数空参数集的方法。
eval
。类似这样的代码应该可以解决问题:[getattr(x, field) for field in dir(x) if hasattr(getattr(x, field), 'order')]
- Samir Talwardef assign_order(order): def orders_decorator(to_func): to_func.__order__ = order return to_func return orders_decorator
- Ashkan