OOP - Attribute
Inhalt
OOP - Attribute¶
(Grundlegendes)
Die genaue Mechanik von Python Klassen zu verstehen benötigt sicher etwas Zeit. Es müssen die Konzepte der Attribute, der Slots, der Property und der Vererbung verstanden werden.
Hier wollen wir uns erstmal auf Attribute konzentrieren.
Attribute¶
In Python besitzen Klassen und Instanzen sogenannte Attribute, welche in Datenattribute und Methodenattribute unterschieden werden können.
Datenattribute sind Datentypen die entweder der Klasse oder den Instanzen zugeordnet sind.
Methodenattribute sind Funktion der Teil einer Klasse sind.
Bemerkung
Attribute |
Kurzbezeichung |
---|---|
Datenattribute |
Attribute |
Methodenattribute |
Methoden |
Klassen¶
Wir definieren wieder unsere Klasse Dog
und wollen untersuchen was Python als Attribute aufgefasst und was nicht.
class Dog:
species = "pet" # class data attribute
def __init__(self, name):
self.name = name # instance data attribute
def speak(self): # instance method attribute
print(f"{self.name} says wow")
paul = Dog('Paul')
print(hasattr(Dog,'species'))
print(hasattr(Dog,'__init__'))
print(hasattr(Dog,'speak'))
print(hasattr(Dog,'name'))
True
True
True
False
print(hasattr(paul,'species'))
print(hasattr(paul,'__init__'))
print(hasattr(paul,'speak'))
print(hasattr(paul,'name'))
True
True
True
True
Das Klassenattribute species
ist also ein Attribut der Klasse Dog
.
Die beiden Instanzmethoden __init__
und speak
sind auch Attribute der Klasse Dog
. Das erscheint widersprüchlich werden doch beide Methoden als Instanzmethoden bezeichnet.
Jedoch brauchen Instanzmethoden immer Instanzen der Klasse. Die Instanzmethoden selbst sind jedoch Attribute der Klasse. Der Funktionsaufruf sollte das deutlich machen:
Dog.speak(paul)
Paul says wow
Das Ausführen der Methode speak()
ist jedoch nicht ohne Instanz möglich. Der Code Dog.speak()
würde zum Fehler führen.
# Dog.speak() # errror
Dagegen können wir auf das Klassenattribut species
auch ohne Instanz zugreifen.
Dog.species
'pet'
Das Instanzdatenattribute name
ist jedoch kein Attribut der Klasse Dog
.
# Dog.name # error
Gewisse Attribute einer Klasse können mit __dict__
angezeigt werden.
Dog.__dict__
mappingproxy({'__module__': '__main__',
'species': 'pet',
'__init__': <function __main__.Dog.__init__(self, name)>,
'speak': <function __main__.Dog.speak(self)>,
'__dict__': <attribute '__dict__' of 'Dog' objects>,
'__weakref__': <attribute '__weakref__' of 'Dog' objects>,
'__doc__': None})
Allerding zeigt nur dir()
alle Attribute einer Klasse an.
dir(Dog)
['__class__',
'__delattr__',
'__dict__',
'__dir__',
'__doc__',
'__eq__',
'__format__',
'__ge__',
'__getattribute__',
'__gt__',
'__hash__',
'__init__',
'__init_subclass__',
'__le__',
'__lt__',
'__module__',
'__ne__',
'__new__',
'__reduce__',
'__reduce_ex__',
'__repr__',
'__setattr__',
'__sizeof__',
'__str__',
'__subclasshook__',
'__weakref__',
'speak',
'species']
Auch hier können wir überprüfen ob name
ein Attribute der Klasse Dog
ist.
'name' in dir(Dog)
False
Wie wir hier sehen sind die Attribute von __dict__
eine Untermenge von dir()
.
# change list1 and list2 to sets, then check if set1 is a subset of set2
def sublist(lst1, lst2):
return set(lst1) <= set(lst2)
sublist(list(Dog.__dict__.keys()),dir(Dog))
True
Bemerkung
Als Instanzattribut werden Daten- und Methodenattribute bezeichnet, deren Verwendung eine Instanz benötigt. Dagegen können Klassenattribute ohne Instanzen verwenden werden.
Die Python Funktion hasattr
liefert leider andere Ergebnisse als der Sprachgebrauch von Python. Das liegt daran, dass hasattr
untersucht ob das Objekt bereits das Attribut.
help(hasattr)
Help on built-in function hasattr in module builtins:
hasattr(obj, name, /)
Return whether the object has an attribute with the given name.
This is done by calling getattr(obj, name) and catching AttributeError.
Instanz¶
Wir wollen nun eine Instanz d
der Klasse Dog
untersuchen.
d = Dog('Max')
d.speak()
Max says wow
print(hasattr(d,'species'))
print(hasattr(d,'__init__'))
print(hasattr(d,'speak'))
print(hasattr(d,'name'))
True
True
True
True
Hier sind nun alle auch Attribute der Instanz.
d.__dict__
{'name': 'Max'}
dir(d)
['__class__',
'__delattr__',
'__dict__',
'__dir__',
'__doc__',
'__eq__',
'__format__',
'__ge__',
'__getattribute__',
'__gt__',
'__hash__',
'__init__',
'__init_subclass__',
'__le__',
'__lt__',
'__module__',
'__ne__',
'__new__',
'__reduce__',
'__reduce_ex__',
'__repr__',
'__setattr__',
'__sizeof__',
'__str__',
'__subclasshook__',
'__weakref__',
'name',
'speak',
'species']
sublist(list(d.__dict__.keys()),dir(d))
True
set(d.__dict__.keys())
{'name'}
set(dir(d))
{'__class__',
'__delattr__',
'__dict__',
'__dir__',
'__doc__',
'__eq__',
'__format__',
'__ge__',
'__getattribute__',
'__gt__',
'__hash__',
'__init__',
'__init_subclass__',
'__le__',
'__lt__',
'__module__',
'__ne__',
'__new__',
'__reduce__',
'__reduce_ex__',
'__repr__',
'__setattr__',
'__sizeof__',
'__str__',
'__subclasshook__',
'__weakref__',
'name',
'speak',
'species'}
set(d.__dict__.keys()).issubset(set(dir(d)))
True
Verwalten von Attributen¶
Methode |
Beschreibung |
---|---|
hasattr() |
- |
setattr() |
- |
getattr() |
- |
delattr() |
- |
class Dog:
def __init__(self, name):
self.name = name # instance data attribute
Lesen und Schreiben von Attributen¶
d = Dog('Max')
d.name
'Max'
setattr(d,'name','Moritz')
getattr(d,'name')
'Moritz'
Hinzufügen und Entfernen Attributen¶
d = Dog('Max')
d.__dict__
{'name': 'Max'}
d.age = 20
d.__dict__
{'name': 'Max', 'age': 20}
delattr(d,'age')
d.__dict__
{'name': 'Max'}
Instanz, Klassen und statische Methoden¶
class TestClass:
def method(self): # instance method
print(self)
@classmethod
def classmethod(cls): # class method
print(cls)
@staticmethod
def staticmethod(): # static method
print("Doing something!")
t = TestClass()
t.method()
<__main__.TestClass object at 0x7f7c58541bb0>
TestClass.classmethod()
<class '__main__.TestClass'>
TestClass.staticmethod()
Doing something!
object - Alles ist ein Objekt¶
In Python ist alles ein Objekt. Ein Objekt ist eine Instanz einer Klasse. Jede Klasse ist von der Python Klasse object
abgleitet.
object
object
dir(object)
['__class__',
'__delattr__',
'__dir__',
'__doc__',
'__eq__',
'__format__',
'__ge__',
'__getattribute__',
'__gt__',
'__hash__',
'__init__',
'__init_subclass__',
'__le__',
'__lt__',
'__ne__',
'__new__',
'__reduce__',
'__reduce_ex__',
'__repr__',
'__setattr__',
'__sizeof__',
'__str__',
'__subclasshook__']
def sublist(lst1, lst2):
return set(lst1) <= set(lst2)
sublist(list(object.__dict__.keys()),dir(object))
True
Im Folgedem wollen wir zeigen das alle Datentypen eine Instanz von der object
Klasse ist.
var=None
print("Der Datentyp "+str(type(var))+" ist eine Instanz der Klasse "+ str(type(object))+" :",isinstance(var,object))
var=1
print("Der Datentyp "+str(type(var))+" ist eine Instanz der Klasse "+ str(type(object))+" :",isinstance(var,object))
var=1.0
print("Der Datentyp "+str(type(var))+" ist eine Instanz der Klasse "+ str(type(object))+" :",isinstance(var,object))
var="String"
print("Der Datentyp "+str(type(var))+" ist eine Instanz der Klasse "+ str(type(object))+" :",isinstance(var,object))
var=['a','b']
print("Der Datentyp "+str(type(var))+" ist eine Instanz der Klasse "+ str(type(object))+" :",isinstance(var,object))
var=('a','b')
print("Der Datentyp "+str(type(var))+" ist eine Instanz der Klasse "+ str(type(object))+" :",isinstance(var,object))
var={'a','b'}
print("Der Datentyp "+str(type(var))+" ist eine Instanz der Klasse "+ str(type(object))+" :",isinstance(var,object))
var={'a':1,'b':2}
print("Der Datentyp "+str(type(var))+" ist eine Instanz der Klasse "+ str(type(object))+" :",isinstance(var,object))
Der Datentyp <class 'NoneType'> ist eine Instanz der Klasse <class 'type'> : True
Der Datentyp <class 'int'> ist eine Instanz der Klasse <class 'type'> : True
Der Datentyp <class 'float'> ist eine Instanz der Klasse <class 'type'> : True
Der Datentyp <class 'str'> ist eine Instanz der Klasse <class 'type'> : True
Der Datentyp <class 'list'> ist eine Instanz der Klasse <class 'type'> : True
Der Datentyp <class 'tuple'> ist eine Instanz der Klasse <class 'type'> : True
Der Datentyp <class 'set'> ist eine Instanz der Klasse <class 'type'> : True
Der Datentyp <class 'dict'> ist eine Instanz der Klasse <class 'type'> : True
Wie wir sehen ist in Python alles ein Objekt.
var=object
print(isinstance(var,object))
True
Selbst ein Objekt ist eine Instanz eines Objektes.
Fortgeschrittene Techniken¶
Tipp
Für weitere Methoden sei auf Objektorientierte Programmierung im Abschnitt Fortgeschrittene
verwiesen.