2009-03-16 8 views
37

私はいくつかの属性を持つオブジェクトのリストを入力として受け取るPythonをデバッグしています。Pythonで匿名オブジェクトを作成することはできますか?

いくつかのテスト値をハードコードしたいと思います。たとえば、 "foo"属性がいくつかの番号に設定されている4つのオブジェクトのリストを考えてみましょう。

これより簡潔な方法はありますか?

x1.foo = 1 
x2.foo = 2 
x3.foo = 3 
x4.foo = 4 
myfunc([x1, x2, x3, x4]) 

理想的には、私はちょうどのようなものと言っできるようにしたいと思います:

myfunc([<foo=1>, <foo=2>, <foo=3>, <foo=4>]) 

を(もちろん、それは作らアップの構文である。しかし、実際に動作することと同様のものがあります。?)

注:これは決してチェックインされません。これは単なるデバッグコードです。読みやすさや保守性について心配しないでください。

答えて

36

私はTethaのソリューションを好むが、それは必要以上に複雑です。

>>> class MicroMock(object): 
...  def __init__(self, **kwargs): 
...   self.__dict__.update(kwargs) 
... 
>>> def print_foo(x): 
...  print x.foo 
... 
>>> print_foo(MicroMock(foo=3)) 
3 
+0

しかし、これらをたくさん作成する場合は、新しい辞書を作成してすべてのエントリをコピーするのではなく、指定した辞書を使用して時間とメモリを節約できます。しかし、本当に重要ではありません。 –

+1

よく、私は主観的かもしれませんが、私は実質的な単純化を見ません。はい、あなたは__init__を使用して更新しますが、あなたはまだ__dict__を手伝っています。 – Tetha

+1

あなたは正しいですが、大幅な簡素化はありません。それはちょうど短く、__new__を使用しません、それだけです。 – DzinX

15

はこれを見ている:


class MiniMock(object): 
    def __new__(cls, **attrs): 
     result = object.__new__(cls) 
     result.__dict__ = attrs 
     return result 

def print_foo(x): 
    print x.foo 

print_foo(MiniMock(foo=3)) 
4

非上品:http://www.hydrogen18.com/blog/python-anonymous-objects.html、と私の限られたテストでは、それが動作するように思える:私はこれを見つけた

def mock(**attrs): 
    r = lambda:0 
    r.__dict__ = attrs 
    return r 

def test(a, b, c, d): 
    print a.foo, b.foo, c.foo, d.foo 

test(*[mock(foo=i) for i in xrange(1,5)]) 
# or 
test(mock(foo=1), mock(foo=2), mock(foo=3), mock(foo=4)) 
26

>>> obj = type('',(object,),{"foo": 1})() 
>>> obj.foo 
1 
3

別の

はここで単純なものです明らかなハック:

直接、私は

myfunc(type('', (object,), {'foo': 3},), type('', (object,), {'foo': 4})) 

アグリー未満冗長任意のワンライナーを知らない匿名オブジェクトで関数を呼び出す

class foo1: x=3; y='y' 
class foo2: y=5; x=6 

print(foo1.x, foo2.y) 

しかし、あなたの正確なユースケースのためのは、ではなく、実際には、仕事をしていません。

2

そのようなPython! O.o

>>> Object = lambda **kwargs: type("Object",(), kwargs) 
>>> person = Object(name = "Bernhard", gender = "male", age = 42) 
>>> person.name 
'Bernhard' 
>>> 

EDIT:大丈夫まあ、技術的にはこれはクラスオブジェクトではなく、オブジェクトのオブジェクトを作成します。しかし、あなたはすぐにインスタンスを作成するために、括弧のペアを追加することによって、最初の行を変更し、匿名オブジェクトかのように扱うことができます:Pythonの3.3のよう

>>> Object = lambda **kwargs: type("Object",(), kwargs)() 
1

を、正確に何をしたいんtypes.SimpleNamespaceがあります:

_ = types.SimpleNamespace 
myfunc([_(foo=1), _(foo=2), _(foo=3), _(foo=4)]) 

そして今、それが実際に架空の構文でにかなり近いです:少し長ったらしいですが、あなたは、別名でそれをクリーンアップすることができます

myfunc([types.SimpleNamespace(foo=1), types.SimpleNamespace(foo=2), types.SimpleNamespace(foo=3), types.SimpleNamespace(foo=4)]) 

あなたの質問。

+0

@RoadieRich以前のコメントではクラス名として '_'を提案しています。 –

関連する問題