2016-10-14 5 views
1

Ich versuche zu sehen, ob eine Instanz eines Attributs bereits für mein Objekt existiert. Wie Sie unten sehen können, möchte ich etwas tun, wenn mein Dog Objekt ein bestimmtes Attribut hat, über die do_something_if_has_aged Methode. Wie kann ich prüfen, ob ein bestimmtes Attribut bereits deklariert wurde? Normalerweise würden Sie überprüfen die Existenz mit so etwas wie dieses, die False zurückgibt:Prüfen, ob sich die Methode bereits im Objekt befindet?

obj = None 
if obj: 
    print(True) 
else: 
    print(False) 

Hier ist meine kleinsten reproduzierbaren Beispiel:

>>> class Dog: 
    def __init__(self, name, age): 
     self.name = name 
     self.age = age 
    def add_years(self, years): 
     self.age += years 
     self.has_aged = True 
    def do_something_if_has_aged(self): 
     if self.has_aged: 
      print("The dog has aged and is %d years closer to death" % self.years) 
     else: 
      print("The dog hasn't aged, apparently.") 


>>> dog = Dog('Spot', 3) 
>>> dog.age 
3 
>>> dog.do_something_if_has_aged() 
Traceback (most recent call last): 
    File "<pyshell#193>", line 1, in <module> 
    dog.do_something_if_has_aged() 
    File "<pyshell#190>", line 9, in do_something_if_has_aged 
    if not self.has_aged: 
AttributeError: 'Dog' object has no attribute 'has_aged' 
>>> dog.add_years(1) 
>>> dog.age 
4 
>>> dog.do_something_if_has_aged() 
The dog hasn't aged, apparently. 

eindeutig der Hund hat Alter, though.

Ich entschuldige mich, wenn der Titel nicht widerspiegelt, was ich unten vermitteln möchte; Ich bin neu in OOP.

+1

Ihr Zustand ist falsch herum: Sie sollten 'if self.has_aged' tun. –

Antwort

3

Anstatt Test f oder das Attribut, setze einen Standardwert für die Klasse; wenn eine Instanz Attribut Python fehlt sucht nach einem Klassenattribut statt:

class Dog: 
    has_aged = False # default for all instances 
    def __init__(self, name, age): 
     self.name = name 
     self.age = age 
    def add_years(self, years): 
     self.age += years 
     self.has_aged = True # sets an instance attribute 
    def do_something_if_has_aged(self): 
     if self.has_aged: 
      print("The dog has aged and is %d years closer to death" % self.years) 
     else: 
      print("The dog hasn't aged, apparently.") 

(beachten Sie, dass ich den Test invertieren, wenn self.has_aged ist wahr Sie in den ersten Zweig gehen wollen, nicht andersrum um).

Oder Sie können einen Standardwert für das Attribut in der __init__ gesetzt:

class Dog: 
    def __init__(self, name, age): 
     self.name = name 
     self.age = age 
     self.has_aged = False 
    def add_years(self, years): 
     self.age += years 
     self.has_aged = True 
    def do_something_if_has_aged(self): 
     if self.has_aged: 
      print("The dog has aged and is %d years closer to death" % self.years) 
     else: 
      print("The dog hasn't aged, apparently.") 

Sie können auch testen, ob ein Attribut mit dem hasattr() function vorhanden ist:

def do_something_if_has_aged(self): 
    if hasattr(self 'has_aged') and self.has_aged: 
     print("The dog has aged and is %d years closer to death" % self.years) 
    else: 
     print("The dog hasn't aged, apparently.") 

oder durch die getattr() function mit mit einem Standardwert:

def do_something_if_has_aged(self): 
    if not getattr(self 'has_aged', False): 
     print("The dog has aged and is %d years closer to death" % self.years) 
    else: 
     print("The dog hasn't aged, apparently.") 

Das dynamische Testen von Attributen sollte jedoch nicht die erste Option sein, die Sie auswählen. einen Klassenstandard zu haben ist viel sauberer.

+0

Was ist der Vorteil von 'has_aged', das eine Klassenvariable anstelle einer Instanzvariablen ist (definiert in' __init__')? –

+1

@JosieThompson: Es gibt nur eine Kopie der Variablen (also ein Speichervorteil); Warum geben Sie allen Instanzen das Attribut, wenn der Standard nur in der Klasse gespeichert werden kann? –

4

Es sieht aus wie Sie für die hasattr integrierte Funktion suchen:

>>> class Dog(object): 
...  pass 
... 
>>> a = Dog() 
>>> hasattr(a, 'age') 
False 
>>> a.age = 7 
>>> hasattr(a, 'age') 
True 

In Ihrem Fall können Sie wie folgt ändern:

def do_something_if_has_aged(self): 
    if hasattr(self, 'has_aged'): 
     pass # do your logic 
1

Ich würde schreiben die __init__ Verfahren einzubeziehen self.has_aged = False zu vermeiden Inspektion zu machen:

class Dog(object): 
    def __init__(self, name, age): 
     self.name = name 
     self.age = age 
     self.has_aged = False # Starting value so it is guaranteed to be defined (unless explicitly deleted). 

Nun sollte der Rest Ihrer Klasse wie geschrieben funktionieren. Allerdings, wenn Sie sehen möchten, ob ein Attribut für ein Objekt definiert wurde, können Sie schreiben:

class Foo(object): 
    def set_bar(self): 
     self.bar = True # Define the attribute bar if it is not yet defined. 

    def is_bar_set(self): 
     return hasattr(self, 'bar') 
1

Um zu überprüfen, ob hasattr mit völlig in Ordnung ist, aber falls Sie sich für eine schnelle Lösung für Sie Code können Sie vor der Hand die Variable als falsch tun initialisieren:

class Dog: 
    has_aged = False 

und die auch Ihren Zustand beheben, wie ich denke, es sollte umgekehrt werden:

def do_something_if_has_aged(self): 
    if self.has_aged: # instead of not self.has_aged 
    print("The dog has aged and is %d years closer to death" % self.years) 
    else: 
    print("The dog hasn't aged, apparently.") 
Verwandte Themen