Objektorientiertes Python - Erweiterte Funktionen
In diesem Artikel werden einige der erweiterten Funktionen von Python vorgestellt
Kernsyntax in unserem Klassendesign
In diesem Artikel werden wir untersuchen, wie Python es uns ermöglicht, Operatoren in unseren Klassen zu nutzen. Python besteht größtenteils aus Objekten und Methoden, die Objekte aufrufen, und dies geht sogar dann weiter, wenn es durch eine praktische Syntax verborgen ist.
>>> var1 = 'Hello'
>>> var2 = ' World!'
>>> var1 + var2
'Hello World!'
>>>
>>> var1.__add__(var2)
'Hello World!'
>>> num1 = 45
>>> num2 = 60
>>> num1.__add__(num2)
105
>>> var3 = ['a', 'b']
>>> var4 = ['hello', ' John']
>>> var3.__add__(var4)
['a', 'b', 'hello', ' John']
Wenn wir also unseren eigenen Klassen die magische Methode __add__ hinzufügen müssen, können wir das auch tun. Versuchen wir das zu tun.
Wir haben eine Klasse namens Sumlist, die einen Konstruktor __init__ hat, der list als Argument namens my_list verwendet.
class SumList(object):
def __init__(self, my_list):
self.mylist = my_list
def __add__(self, other):
new_list = [ x + y for x, y in zip(self.mylist, other.mylist)]
return SumList(new_list)
def __repr__(self):
return str(self.mylist)
aa = SumList([3,6, 9, 12, 15])
bb = SumList([100, 200, 300, 400, 500])
cc = aa + bb # aa.__add__(bb)
print(cc) # should gives us a list ([103, 206, 309, 412, 515])
Ausgabe
[103, 206, 309, 412, 515]
Es gibt jedoch viele Methoden, die intern von anderen magischen Methoden verwaltet werden. Unten sind einige von ihnen,
'abc' in var # var.__contains__('abc')
var == 'abc' # var.__eq__('abc')
var[1] # var.__getitem__(1)
var[1:3] # var.__getslice__(1, 3)
len(var) # var.__len__()
print(var) # var.__repr__()
Erben von integrierten Typen
Klassen können auch von integrierten Typen erben. Dies bedeutet, dass sie von allen integrierten Typen erben und alle dort verfügbaren Funktionen nutzen.
Im folgenden Beispiel erben wir vom Wörterbuch, implementieren dann aber eine seiner Methoden __setitem__. Dies (setitem) wird aufgerufen, wenn wir Schlüssel und Wert im Wörterbuch festlegen. Da dies eine magische Methode ist, wird dies implizit aufgerufen.
class MyDict(dict):
def __setitem__(self, key, val):
print('setting a key and value!')
dict.__setitem__(self, key, val)
dd = MyDict()
dd['a'] = 10
dd['b'] = 20
for key in dd.keys():
print('{0} = {1}'.format(key, dd[key]))
Ausgabe
setting a key and value!
setting a key and value!
a = 10
b = 20
Lassen Sie uns unser vorheriges Beispiel erweitern. Im Folgenden haben wir zwei magische Methoden namens __getitem__ und __setitem__ genannt, die besser aufgerufen werden, wenn wir uns mit dem Listenindex befassen.
# Mylist inherits from 'list' object but indexes from 1 instead for 0!
class Mylist(list): # inherits from list
def __getitem__(self, index):
if index == 0:
raise IndexError
if index > 0:
index = index - 1
return list.__getitem__(self, index) # this method is called when
# we access a value with subscript like x[1]
def __setitem__(self, index, value):
if index == 0:
raise IndexError
if index > 0:
index = index - 1
list.__setitem__(self, index, value)
x = Mylist(['a', 'b', 'c']) # __init__() inherited from builtin list
print(x) # __repr__() inherited from builtin list
x.append('HELLO'); # append() inherited from builtin list
print(x[1]) # 'a' (Mylist.__getitem__ cutomizes list superclass
# method. index is 1, but reflects 0!
print (x[4]) # 'HELLO' (index is 4 but reflects 3!
Ausgabe
['a', 'b', 'c']
a
HELLO
Im obigen Beispiel legen wir eine Liste mit drei Elementen in Mylist fest und implizit wird die Methode __init__ aufgerufen. Wenn wir das Element x drucken, erhalten wir die Liste mit drei Elementen (['a', 'b', 'c']). Dann fügen wir dieser Liste ein weiteres Element hinzu. Später fragen wir nach Index 1 und Index 4. Wenn Sie jedoch die Ausgabe sehen, erhalten wir ein Element aus dem (Index-1), nach dem wir gefragt haben. Wie wir wissen, beginnt die Indizierung der Liste bei 0, aber hier beginnt die Indizierung bei 1 (deshalb erhalten wir das erste Element der Liste).
Regeln der Namensgebung
In diesem Artikel werden Namen untersucht, die für Variablen verwendet werden, insbesondere für private Variablen und Konventionen, die von Python-Programmierern weltweit verwendet werden. Obwohl Variablen als privat bezeichnet werden, gibt es in Python keine Privatsphäre und dies ist beabsichtigt. Wie jede andere gut dokumentierte Sprache hat Python Namens- und Stilkonventionen, die es fördert, obwohl es sie nicht erzwingt. Es gibt einen Styleguide von “Guido van Rossum” the originator of Python, that describe the best practices and use of name and is called PEP8. Here is the link for this, https://www.python.org/dev/peps/pep-0008/
PEP steht für Python Enhancement Proposal und ist eine Reihe von Dokumentationen, die in der Python-Community verteilt wurden, um vorgeschlagene Änderungen zu diskutieren. Zum Beispiel wird allen empfohlen,
- Modulnamen - all_lower_case
- Klassennamen und Ausnahmenamen - CamelCase
- Globale und lokale Namen - all_lower_case
- Funktionen und Methodennamen - all_lower_case
- Konstanten - ALL_UPPER_CASE
Dies ist nur die Empfehlung, Sie können variieren, wenn Sie möchten. Da die meisten Entwickler dieser Empfehlung folgen, ist Ihr Code möglicherweise weniger lesbar.
Warum Konventionen einhalten?
Wir können der PEP-Empfehlung folgen, die wir erhalten können.
- Der überwiegenden Mehrheit der Entwickler vertrauter
- Für die meisten Leser Ihres Codes klarer.
- Entspricht dem Stil anderer Mitwirkender, die auf derselben Codebasis arbeiten.
- Zeichen eines professionellen Softwareentwicklers
- Jeder wird dich akzeptieren.
Variablennamen - 'Öffentlich' und 'Privat'
Wenn wir in Python mit Modulen und Klassen arbeiten, bestimmen wir einige Variablen oder Attribute als privat. In Python gibt es keine "private" Instanzvariable, auf die nur innerhalb eines Objekts zugegriffen werden kann. Privat bedeutet einfach, dass sie nicht für die Benutzer des Codes bestimmt sind, sondern für die interne Verwendung. Im Allgemeinen wird von den meisten Python-Entwicklern eine Konvention befolgt, z. B. ein Name, dem beispielsweise ein Unterstrich vorangestellt ist. _attrval (Beispiel unten) sollte als nicht öffentlicher Teil der API oder eines beliebigen Python-Codes behandelt werden, unabhängig davon, ob es sich um eine Funktion, eine Methode oder ein Datenelement handelt. Nachfolgend finden Sie die Namenskonvention, der wir folgen:
Öffentliche Attribute oder Variablen (die vom Importeur dieses Moduls oder vom Benutzer dieser Klasse verwendet werden sollen) -regular_lower_case
Private Attribute oder Variablen (interne Verwendung durch das Modul oder die Klasse) -_single_leading_underscore
Private Attribute, die nicht in Unterklassen unterteilt werden sollten -__double_leading_underscore
Magische Attribute -__double_underscores__(benutze sie, erstelle sie nicht)
class GetSet(object):
instance_count = 0 # public
__mangled_name = 'no privacy!' # special variable
def __init__(self, value):
self._attrval = value # _attrval is for internal use only
GetSet.instance_count += 1
@property
def var(self):
print('Getting the "var" attribute')
return self._attrval
@var.setter
def var(self, value):
print('setting the "var" attribute')
self._attrval = value
@var.deleter
def var(self):
print('deleting the "var" attribute')
self._attrval = None
cc = GetSet(5)
cc.var = 10 # public name
print(cc._attrval)
print(cc._GetSet__mangled_name)
Ausgabe
setting the "var" attribute
10
no privacy!