我正在尝试编写一个能够执行以下操作的Python类:
c = MyClass()
a = c.A("a name for A") # Calls internally c.create("A", "a name for A")
b = c.B("a name for B") # Calls internally c.create("B", "a name for B")
A和B可以是任何东西(好吧,它们是在数据库中定义的,但我不想在我的代码中明确定义它们)
一个hacky解决方法是执行以下操作:
class MyClass():
def __init__(self):
self.createItem = ""
def create(self, itemType, itemName):
print "Creating item %s with name %s" % (itemType, itemName)
def create_wrapper(self, name):
self.create(self.createItem, name)
def __getattr__(self, attrName):
self.createItem = attrName
return self.create_wrapper
当用户调用类似的内容时,这将起作用:
a = c.A("nameA")
b = c.B("nameB")
但是,在没有被调用的情况下存储函数指针的情况下它会被忽略:
aFunc = c.A
bFunc = c.B
aFunc("nameA") # Is actually calling c.create("B", "nameA"),
# as c.B was the last __getattr__() call
bFunc("nameB")
对于我在这里缺少的任何建议?
由于
编辑:我似乎只想出了这个,但菲利普有一个更优雅的解决方案......
我的解决方案是:
class MyClassCreator():
def __init__(self, origClass, itemType):
self.origClass = origClass
self.itemType = itemType
def create_wrapper(self, name):
return self.origClass.create(self.itemType, name)
class MyClass():
def __init__(self):
self.createItem = ""
def create(self, itemType, itemName):
print "Creating item %s with name %s" % (itemType, itemName)
def __getattr__(self, attrName):
return MyClassCreator(self, attrName).create_wrapper
我实际上最终使用的版本(因为我需要比单个参数更复杂):(我不知道是否可以使用lambda函数完成...)
def __getattr__(self, attrName):
def find_entity_wrapper(*args, **kwargs):
return self.find_entity(attrName, *args, **kwargs)
return find_entity_wrapper
答案 0 :(得分:8)
让__getattr__
返回本地包装函数:
class MyClass(object):
def create(self, itemType, itemName):
print "Creating item %s with name %s" % (itemType, itemName)
def __getattr__(self, attrName):
def create_wrapper(name):
self.create(attrName, name)
return create_wrapper
还有其他方法可以创建包装函数。在这种情况下,最简单的方法是使用functools.partial
:
import functools
class MyClass(object):
def create(self, itemType, itemName, *args, **kwargs):
print "Creating item %s with name %s, args %r and kwargs %r" % (itemType, itemName, args, kwargs)
def __getattr__(self, attrName):
return functools.partial(self.create, attrName)
c = MyClass()
bFunc = c.B
bFunc("nameB", 1, 2, foo=3)
这将自动将所有剩余的args传递给包装函数。
答案 1 :(得分:6)
你可以通过简化来获得你想要的东西:
class MyClass():
def create(self, itemType, itemName):
print "Creating item %s with name %s" % (itemType, itemName)
def __getattr__(self, attrName):
return lambda x: self.create(attrName, x)
c = MyClass()
a = c.A("nameA")
b = c.B("nameB")
af = c.A
bf = c.B
af("nameA")
bf("nameB")
打印:
Creating item A with name nameA
Creating item B with name nameB
Creating item A with name nameA
Creating item B with name nameB