Python:允许调用未明确定义的方法 ala __getattr__
我正在尝试编写一个能够执行以下操作的 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 可以是任何东西(好吧,它们是在数据库中定义的,但我不想在代码中显式定义它们
)黑客的解决方法是执行以下操作:
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
I'm trying to write a Python class that has the ability to do the following:
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 and B could be anything (well, they're defined in a database, but I don't want to explicitly define them in my code)
A hacky workaround for it would be to do the following:
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
This will work when the user calls something like:
a = c.A("nameA")
b = c.B("nameB")
However, it will fall over in situations where the function pointers are stored without being called:
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")
Any suggestions for anything I'm missing here?
Thanks
Edit: I appear to have just figured this one out, but Philipp has a far more elegant solution....
My solution was:
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
The version that I actually ended up using (as I needed more complexity than a single argument) is: (I don't know if this can be done using a lambda function...)
def __getattr__(self, attrName):
def find_entity_wrapper(*args, **kwargs):
return self.find_entity(attrName, *args, **kwargs)
return find_entity_wrapper
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
让 __getattr__ 返回本地包装函数:
还有其他方法可以创建包装函数。在这种情况下,最简单的一种是使用 functools.partial:
这会自动将所有剩余的参数传递给包装函数。
Have
__getattr__
return a local wrapper function:There are other ways to create the wrapper function. The simplest one in this case is to use
functools.partial
:This will automatically pass all remaining args to the wrapped function.
您可以通过简化来获得您想要的:
打印:
You can get what you want by simplifying:
prints: