Python:允许将未专门定义的方法称为ala\uu getattr__

Python:允许将未专门定义的方法称为ala\uu getattr__,python,class,methods,Python,Class,Methods,我正在尝试编写一个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") class MyClass(): def __init__(self): self.create

我正在尝试编写一个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")
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和B可以是任何东西(它们在数据库中定义,但我不想在代码中显式定义)

对于it来说,一个棘手的解决办法是执行以下操作:

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")
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函数完成此操作…)


\uuuu getattr\uuuu
返回本地包装函数:

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)

这将自动将所有剩余的参数传递给包装函数。

您可以通过简化以下内容来获得所需的参数:

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

我不确定我最喜欢你和Ned的解决方案中的哪一个,但它们都比我提出的解决方案好得多(见我上面问题的编辑部分)。它们没有太大的不同。我的版本只是lambda版本的详细变体。在Python中,lambda有时因其限制性和难以阅读而受到反对,但在语义上它们与命名函数是等价的。通常我只对不修改状态的简单表达式使用lambdas和其他类似函数的构造。我将最终使用的实际函数放在问题的底部-我实际上需要能够传递任意数量的参数,我不确定它是否能与lambda函数一起工作……您是否正在尝试实现一个
Mock
库?谢谢-看起来非常优雅!我以前从来没有在兰博达周围动过脑筋-也许现在应该是时候这么做了。。。我要么走这条路,要么按菲利普建议的路走。。。任何一种方法都适合我!谢天谢地,我的问题中的例子是一个非常简单的例子——我实际上需要能够传递一个变量(kwargs)数量的参数,我相信我不能用lambda做到这一点。。。不确定,但很高兴看到Philipp的解决方案能够很好地支持这一点。再次感谢。