2009-03-16 8 views
37

मैं कुछ पायथन डीबग कर रहा हूं जो इनपुट के रूप में, वस्तुओं की एक सूची, प्रत्येक विशेषता के साथ प्रत्येक लेता है।क्या पाइथन में अज्ञात वस्तुएं बनाना संभव है?

मैं कुछ परीक्षण मूल्यों को हार्ड-कोड करना चाहता हूं - मान लीजिए, चार वस्तुओं की एक सूची जिसका "foo" विशेषता कुछ संख्या पर सेट है।

क्या इससे कोई और संक्षिप्त तरीका है?

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

एक और

यहाँ सरल कुछ स्पष्ट हैक:

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

print(foo1.x, foo2.y) 

लेकिन अपने सटीक USECASE के लिए, अनाम वस्तुओं के साथ एक समारोह बुला सीधे, मैं किसी भी एक लाइनर से

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

बदसूरत कम वर्बोज़ पता नहीं है, काम करता है, लेकिन वास्तव में नहीं।

2

तो संक्षिप्त, ऐसे पायथन! O.o

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

संपादित करें: ठीक है, ठीक है, तकनीकी रूप से यह एक वर्ग वस्तु, नहीं एक वस्तु वस्तु बनाता है। लेकिन आप इसे एक गुमनाम वस्तु की तरह व्यवहार कर सकते हैं या आप तुरंत एक उदाहरण बनाने के लिए कोष्ठक की एक जोड़ी जोड़कर पहली पंक्ति को संशोधित:

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

अजगर 3.3 के रूप में, वहाँ types.SimpleNamespace करता है कि आप क्या चाहते हैं:

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

कि एक बालक अधिक शब्दों वाले है, लेकिन आप यह साफ कर सकते हैं उपनाम वाले:

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

और अब है कि वास्तव में सुंदर में काल्पनिक वाक्य रचना के काफी करीब है आपका प्रश्न।

+0

@RoadieRich को क्रेडिट पहले की टिप्पणी में वर्ग नाम के रूप में '_' का सुझाव देने के लिए। –

संबंधित मुद्दे