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")
5
2
私は、次のことを行う機能を持つ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
私が実際に使用したバージョン(単一の引数よりも複雑さが必要なため)は次のとおりです(ラムダ関数を使用してこれを行うことができるかどうかわかりません…)
def __getattr__(self, attrName): def find_entity_wrapper(*args, **kwargs): return self.find_entity(attrName, *args, **kwargs) return find_entity_wrapper
2 Answer
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)
これにより、残りのすべての引数が自動的にラップされた関数に渡されます。
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