伙计们。我最近开始学习课程,并且在玩耍时尝试做这样的事情:
from functools import partial
class test():
def __init__(self):
exec('def foo(self, number): x = number; return x')
def printingX(self):
command = partial(self.foo, 1)
print command
a = test()
a.printingX()
这当然是一个错误,但是我的问题是:是否可以将方法存储在“ init ”内部,然后在以后的其他方法中调用它?如果可能的话,这是一个好的做法还是不好的做法?
答案 0 :(得分:2)
您可以,但是通常不能。
我会说be careful with exec。但是除此之外,没有什么阻止您真正做到这一点
>>> class MyClass:
... def __init__(self):
... exec('MyClass.foo = lambda self, x: x*x')
...
>>> c = MyClass()
>>> c.foo(3)
9
ALTHOUGH,我的建议是您不要这样做,因为这是非常不切实际的,并且没有惯例。
答案 1 :(得分:0)
是否可以将方法存储在'init'中
取决于“存储”是什么意思?但是,如果您要表示“定义”,是的,您可以定义函数(nb:def
总是定义一个函数,仅当在类或实例上查询时,它才成为“方法”)。而且您不需要exec
:
class Foo(object):
def __init__(self, arg):
def bar(baaz):
print("in bar: {}".format(baaz))
bar(arg)
然后在其他方法中调用它?
如果要使其成为方法,可以将其添加到实例中:
class Foo(object):
def __init__(self, arg):
self.arg = arg
def bar(self):
print("in self.bar: {}".format(self.arg))
self.bar = bar.__get__(self, type(self))
或该类(这意味着您每次实例化该类都会被覆盖):
class Foo(object):
def __init__(self, arg):
self.arg = arg
def bar(self):
print("in self.bar: {}".format(self.arg))
type(self).bar = bar
如果可能的话,这是个好习惯吗?
正如上面所写,它是荒谬的,令人困惑的且效率低下的,所以我看不到如何将其视为良好实践。而使用exec
进行操作只是一个完整的WTF。
如果目标是以某种方式为每个实例参数化给定方法(基于条件或其他条件),则可以将函数(或任何可调用的FWIW)作为参数传递(python函数是与其他对象一样的对象):
class Foo(object):
def __init__(self, arg, strategy):
self.arg = arg
# we may not want to expose it
# as part of the class API
self._strategy = strategy
def bar(self, value):
return self._strategy(self, value)
def my_strategy(foo, value):
return foo.arg * value
f = Foo(42, my_strategy)
f.bar(2)
FWIW,这被称为“策略”设计模式。
答案 2 :(得分:0)
您可以完全按照自己的意愿进行操作,但是必须使用exec
的globals和locals参数来限制执行危险字符串并获取函数定义的风险:
class test:
def __init__(self):
funcs = {}
exec('def foo(self, number): x = number; return x',
{'__builtins__':{}}, funcs)
for func in funcs:
if not hasattr(self.__class__, func):
setattr(self.__class__, func, funcs[func])
此代码在创建第一个对象时明确地将编译后的函数添加到类中。
演示:
>>> test.__dict__
mappingproxy({'__module__': '__main__', '__init__': <function test.__init__ at 0x000001E5C5F27EA0>, '__dict__': <attribute '__dict__' of 'test' objects>, '__weakref__': <attribute '__weakref__' of 'test' objects>, '__doc__': None})
>>> t = test()
>>> test.__dict__
mappingproxy({'__module__': '__main__', '__init__': <function test.__init__ at 0x000001E5C5F27EA0>, '__dict__': <attribute '__dict__' of 'test' objects>, '__weakref__': <attribute '__weakref__' of 'test' objects>, '__doc__': None, 'foo': <function foo at 0x000001E5C5F27F28>})
>>> t.foo(12)
12
这清楚地表明,foo
方法在创建其第一个实例时已添加到该类中。
但是... 请不要!。这段代码仅显示Python足够友好,可以在运行时修改类,而如果一个类的属性恰巧是一个函数,则该方法是可以的。好的,传递给exec的字符串是受控制的,因此这里没有安全性问题,但是应尽可能避免使用exec
和eval
。
除非您真正需要这样的代码,否则当可读性成为Python程序员的首要考虑因素时,这将导致难以理解的类。
所以回答您的第二个问题确实是一个可怕的做法。永远不要说我建议使用它。