2010-10-14 7 views
6

Mam klasę Foo z metodą isValid. Następnie mam pasek metod(), który odbiera obiekt Foo i którego zachowanie zależy od tego, czy jest poprawne czy nie.Jaki jest najbardziej ogólny typ python, do którego mogę dodać atrybuty?

Do testowania tego, chciałem przekazać obiekt do paska, którego metoda isValid zawsze zwraca wartość False. Z innych powodów nie mogę utworzyć obiektu Foo w czasie testowania, więc potrzebowałem obiektu do sfałszowania go. Najpierw pomyślałem o stworzeniu najbardziej ogólnego obiektu i dodanie do niego atrybutuValid, aby użyć go jako Foo. Ale to nie do końca pracy:

>>> foo = object() 
>>> foo.isValid = lambda : False 
Traceback (most recent call last): 
    File "<stdin>", line 1, in <module> 
AttributeError: 'object' object has no attribute 'isValid' 

I okazało się, obiekt nie posiada __dict__, więc nie można dodać atrybutów do niego. W tym momencie, obejście używam jest stworzenie typ w locie w tym celu, a następnie tworząc obiekt tego typu:

>>> tmptype = type('tmptype',(), {'isValid' : lambda self : False}) 
>>> x = tmptype() 
>>> x.isValid() 
False 

Ale to wydaje się zbyt długi strzał. Musi istnieć jakiś ogólnie dostępny rodzaj, który mógłbym użyć do tego celu, ale który?

Odpowiedz

6

masz dobry pomysł, ale możesz uczynić go bardziej ogólnym. Albo

tmptype = type('tmptype', (object,) {}) 

lub

class tmptype(object): 
    pass 

Następnie można po prostu zrobić

foo = tmptype() 
foo.is_valid = lambda: False 

jakbyś chciał zrobić z object. W ten sposób możesz użyć tej samej klasy dla wszystkich dynamicznych, monik-łatających potrzeb.

+0

Cóż, w zasadzie to samo jest rozłożone na więcej linii iz nową klasą stylu. Ale moje pytanie wciąż trwa: czy nie ma jakiegoś ogólnie dostępnego rodzaju, aby osiągnąć ten sam cel? Coś jak obiekt z __dict__? Czy naprawdę muszę stworzyć typ tylko do tego? – ricab

+0

@ricab: Oto odrzucenie idei, którą właśnie ściągnąłem google. Możesz znaleźć innych. http://mail.python.org/pipermail/python-bugs-list/2007- January/036866.html – aaronasterling

+0

Oh, ok, więc nie ma takiego typu. Chociaż prawdopodobnie po prostu tęskniłem za tym ... Dzięki – ricab

1

dlaczego musisz go skomplikować? Myślę, że najprostszym sposobem (i „standardowy” sposób) jest zrobić

class FakeFoo(object): 
    def is_valid(): 
     return False 

poza tym zastosowanie lambda nie jest dobre w tym kontekście ... spójrz na to: http://python-history.blogspot.com/2009/04/origins-of-pythons-functional-features.html jest przez BDFL

i tak dalej ...

+0

Ponieważ nie chcę rozpraszać czytelnika dodatkowymi zajęciami, których użycie może spowodować, że będzie on pod wrażeniem i do którego może być zmuszony.Ponadto, ponieważ w ten sposób definicja typu jest w jedynym miejscu, w którym tworzony jest jego jedyny obiekt, w jednym celu można go od razu znaleźć. Definicja jest tam, gdzie jest używana, co pozwala na niezależność testu. Gdy zobaczysz obiekt, zobaczysz definicję typu, a kiedy zobaczysz definicję typu, wiesz, że jest to jego jedyny cel. Cel zarówno obiektu, jak i typu jest jasny bez konieczności szukania gdzie indziej. – ricab

+0

Nawiasem mówiąc, czytałem artykuł i nie rozumiem, jak to się dzieje, że użycie lambda nie jest dobre w kontekście ... – ricab

+0

wiem, że jest to w jednym celu i tak dalej ... ale to nie jest we właściwy sposób to zrobić, w mojej opinii ... mogę napisać spróbuj: a.next() z wyjątkiem StopIterationError: przekaż intead z dla x w: #pass, ale to nie jest poprawny sposób ... wiem w niektórych przypadkach możesz go użyć, ale dlaczego miałbyś to robić? Moim zdaniem, mówię ... artykuł dotyczył użycia lambda i napisano, że lambda nie powinna być używana zamiast normalnej "def", ale tylko wtedy, gdy python wymaga wyrażenia, a nie instrukcji. ... tak, możesz to zrobić, ale nie rozrzedzam k, jest to właściwe podejście do problemu ... – Ant