Python: Unterschied zwischen den Versionen

Aus Info-Theke
Zur Navigation springen Zur Suche springen
 
(24 dazwischenliegende Versionen von 7 Benutzern werden nicht angezeigt)
Zeile 1: Zeile 1:
[[Kategorie:Sprache]]
[[Kategorie:Sprache]]
= Links =
* [[Jupyter]]
* https://www.python.org/downloads/windows/
= Exception =
= Exception =
<pre>
<syntaxhighlight lang="python">
try:
try:
   raise Exception("not allowed")
   raise Exception("not allowed")
Zeile 14: Zeile 18:
finally:
finally:
   closeIt()
   closeIt()
</pre>
</syntaxhighlight>


= Regular Expression =
= Regular Expression =
<pre>
<syntaxhighlight lang="python">
import re
import re
rexpr = re.compile(r"([\da-z]+)")
rexpr = re.compile(r"([\da-z]+)")
Zeile 23: Zeile 27:
if match != None:
if match != None:
   number = (int) rexpr.group(1)
   number = (int) rexpr.group(1)
</pre>
# Replacement:
regex = re.compile(r"A\d+", re.IGNORECASE)
for line in some_file:
    other = regex.sub('<Id>', line)
# Replacement mit Referenzen:
s = 'aaa@xxx.com bbb@yyy.net ccc@zzz.org'
re.sub('([a-z]+)@([a-z]+)', r'\2@\1', s)
</syntaxhighlight>


= Datentypen =
= Datentypen =
== String ==
== String ==
* "x" und 'x' sind gleichwertig
* "x" und 'x' sind gleichwertig
* Formatierung
=== Formatierung ===
** f-String
* f-String
<syntaxhighlight lang="python">
<syntaxhighlight lang="python">
# Gleitpunktzahl mit 3 Stellen ausgeben:
# Gleitpunktzahl mit 3 Stellen ausgeben:
Zeile 35: Zeile 46:
# 2-stellig mit führender 0 ausgeben:
# 2-stellig mit führender 0 ausgeben:
f'{sec//3600}:{sec%3600//60:02}:{sec%60:02}'
f'{sec//3600}:{sec%3600//60:02}:{sec%60:02}'
# String linksbündig:
f'{data:<10}'
# String rechtsbündig:
f'{data:>10}'
</syntaxhighlight>
</syntaxhighlight>
** str.format()
* str.format()
<syntaxhighlight lang="python">
<syntaxhighlight lang="python">
"{:3.7f} {:s} {:07d}".format(3.14, "hello", 100)
"{:3.7f} {:s} {:07d}".format(3.14, "hello", 100)
"{0:d} / {0:x}".format(714)
"{0:d} / {0:x}".format(714)
"{}-{}: {}".format('abc.txt', 9, 7.99)
"{}-{}: {}".format('abc.txt', 9, 7.99)
precision=2
'{:.Pf}'.replace('P', str(precision)).format(value)
</syntaxhighlight>
</syntaxhighlight>
* Bytes -> String: b'data'.decode("utf-8")
* Bytes -> String: b'data'.decode("utf-8")
Zeile 64: Zeile 81:


== Dictionary==
== Dictionary==
<pre>
<syntaxhighlight lang="python">
x = { 'key' : 'val', 'xyz': 3 }
x = { 'key' : 'val', 'xyz': 3 }
x['key'] = value
x['key'] = value
Zeile 70: Zeile 87:
contains = 'key' in x and 'key2' not in x
contains = 'key' in x and 'key2' not in x
size = len(x)
size = len(x)
for pair in x.iteritems():
for key, value in x.items():
   key = pair[0]
   print(key, value)
for key in x.iterkeys():
for key in x:
   print key
   print key
</pre>
</syntaxhighlight>
* x.itervalues()
* x.itervalues()
* x.setdefault(key[, value]): setzt Wert nur, wenn noch nicht gesetzt
* x.setdefault(key[, value]): setzt Wert nur, wenn noch nicht gesetzt
Zeile 82: Zeile 99:


== Mengen ==
== Mengen ==
<pre>
<syntaxhighlight lang="python">
s = set(['y', 3]) ; f = frozenset(['y', 3])  
s = {3, 'sjoerd'}
s = {c for c in 'abracadabra' if c not in 'abc'}
assertEquals(s, {'d', 'r'})
iterable = ['y', 3];
s = set(iterable) ;  
f = frozenset(iterable)
s.add(9)
s.remove(9)  
for elem in s:
for elem in s:
   print elem
   print elem
Zeile 92: Zeile 116:
isPartOf = s <= f
isPartOf = s <= f
diff = s - f
diff = s - f
</pre>
</syntaxhighlight>


== Datum/Zeit ==
== Datum/Zeit ==
<pre>import datetime, time
<syntaxhighlight lang="python">
import datetime, time
# ab hour optional:
# ab hour optional:
date1 = datetime.datetime(2019, 4, 1, 22, 44, 12, 123456)
date1 = datetime.datetime(2019, 4, 1, 22, 44, 12, 123456)
Zeile 125: Zeile 150:
diffSec = (date1 - date2).total_seconds()
diffSec = (date1 - date2).total_seconds()
diffDays = (date1 - date2).days
diffDays = (date1 - date2).days
</pre>
</syntaxhighlight>
 
=== Leistungsmessung ===
<syntaxhighlight lang="python">
import timeit
body = '''text = 'abcdefg'
s = list(text)
s[6] = 'W'
''.join(s)
'''
print(timeit.timeit(body, number=1000000))
</syntaxhighlight>


== Enum ==
== Enum ==
<pre>from enum import Enum
<syntaxhighlight lang="python">
from enum import Enum
class TokenType(Enum):
class TokenType(Enum):
   digit = 1 ; string = 2 ; id = 3 ; operator = 4
   digit = 1 ; string = 2 ; id = 3 ; operator = 4


x = TokenType.id
x = TokenType.id
</pre>
for item in TokenType:
  print(item.name)
</syntaxhighlight>


== Typcheck ==
== Typcheck ==
<pre>
<syntaxhighlight lang="python">
isStringOrSubclass = isinstance(aVariable, str)
isStringOrSubclass = isinstance(aVariable, str)
isString = type(aVariable) is str
isString = type(aVariable) is str
isList = type([1, 2]) is list
isList = type([1, 2]) is list
isDict = type({ 0:"a", 1:"b" }) is dict
isDict = type({ 0:"a", 1:"b" }) is dict
</pre>
</syntaxhighlight>


== Spezielle Methoden/Attribute ==
== Spezielle Methoden/Attribute ==
* Statische Methoden:
* Statische Methoden:
<pre>
<syntaxhighlight lang="python">
class X:
class X:
   # statische Variable
   # statische Variable
Zeile 154: Zeile 193:


X.add("new")
X.add("new")
</pre>
</syntaxhighlight>
* Feststellen, ob Attribut existiert: hasattr(instance, nameOfAttribute)
* Feststellen, ob Attribut existiert: hasattr(instance, nameOfAttribute)
* dynamischer Code:
* dynamischer Code:
<pre>
<syntaxhighlight lang="python">
exec 'import ' + module
exec 'import ' + module
</pre>
</syntaxhighlight>
* Vollständige Kopie (deep copy):
* Vollständige Kopie (deep copy):
<pre>
<syntaxhighlight lang="python">
import copy
import copy
x = [1, 2]
x = [1, 2]
y = copy.deepcopy(x)
y = copy.deepcopy(x)
</pre>
</syntaxhighlight>
* Superclass-Konstruktor:
* Superclass-Konstruktor:
<pre>
<syntaxhighlight lang="python">
class Parent:
class Parent:
   def __init__(self, name)
   def __init__(self, name)
Zeile 174: Zeile 213:
   def __init__(self, name):
   def __init__(self, name):
       Parser.__init__(self, name)
       Parser.__init__(self, name)
</pre>
</syntaxhighlight>


== Funktionale Programmierung ==
== Funktionale Programmierung ==
<pre>
<syntaxhighlight lang="python">
import functools, math
import functools, math
array = [ 1, 9, 7, 5 ]
array = [ 1, 9, 7, 5 ]
Zeile 183: Zeile 222:
squares = list(map(lambda x: x*x, array))
squares = list(map(lambda x: x*x, array))
squares2 = list(filter(lambda x: int(math.sqrt(x)) == math.sqrt(x), array))
squares2 = list(filter(lambda x: int(math.sqrt(x)) == math.sqrt(x), array))
</pre>
</syntaxhighlight>


= Typische Situationen =
= Typische Situationen =
== Division Integer ==
<syntaxhighlight lang="python">
pairs = count // 2
</syntaxhighlight>
== Objekte kopieren (Shallow/Deep Copy) ==
<syntaxhighlight lang="python">
import copy
a = [1, 2, 3]
b = copy.copy(a)
c = [a, [1, 2, 3]]
d = copy.deepcopy(c)
# Speziell bei Listen (shallow copy):
copied_list = original_list[:]
</syntaxhighlight>
== Sortieren ==
== Sortieren ==
<pre>a =["Joe", "Eve", "Bob", "alma", "Adam"]
<syntaxhighlight lang="python">
a =["Joe", "Eve", "Bob", "alma", "Adam"]
a.sort()
a.sort()
# sort by a global function:
# sort by a global function:
Zeile 193: Zeile 251:
# sort by a lambda function which calculates the sorting key:
# sort by a lambda function which calculates the sorting key:
a.sort(key=lambda x: x[2])
a.sort(key=lambda x: x[2])
</pre>
# 2-stufig: nach Länge absteigend, dann alphabetisch:
a.sort(key=lambda x: (-len(x), x))
# comparism function:
def mySort(a, b): return len(a) - len(b)
import functools
a.sort(key=functools.cmp_to_key(mySort))
</syntaxhighlight>


== Externes Programm aufrufen ==
== Externes Programm aufrufen ==
<pre>
<syntaxhighlight lang="python">
with supbprocess.popen([ '/usr/bin/wc', '-l', file ], stdout=subprocess.PIPE) as proc:
with supbprocess.popen([ '/usr/bin/wc', '-l', file ], stdout=subprocess.PIPE) as proc:
   count = int(proc.stdout.read().decode())
   count = int(proc.stdout.read().decode())
</pre>
</syntaxhighlight>


== Dateien ==
== Dateien ==
* Lesen:
* Lesen:
<pre>
<syntaxhighlight lang="python">
with open(self._filename, "r") as fp:
with open(self._filename, "r") as fp:
   for line in fp:
   for line in fp:
     print(line)
     print(line)
   # fp.close() ist implizit
   # fp.close() ist implizit
</pre>
</syntaxhighlight>
* Binärdatei:
<syntaxhighlight lang="python">
with open(self._filename, "rb") as fp:
  data = fp.read(8000)
  while data:
    doIt(data)
    data = fp.read(8000)
</syntaxhighlight>
 
* Schreiben:
* Schreiben:
<pre>
<syntaxhighlight lang="python">
with open(self._filename, "w") as fp, open(self._input, "r") as fpInp:
with open(self._filename, "w") as fp, open(self._input, "r") as fpInp:
   line = fpInp.read()
   line = fpInp.read()
   fp.write(line);
   fp.write(line);
</pre>
</syntaxhighlight>


= Sprachbesonderheiten =
= Sprachbesonderheiten =
== Typinfo ==
== Variable Zahl Parameter in Methode: Liste ==
<pre>
<syntaxhighlight lang="python">
# numbers ist eine Liste:
def find_sum(*numbers):
    result = 0
    for num in numbers:
        result = result + num
   
    print("Sum = ", result)
 
# function call with 3 arguments
find_sum(1, 2, 3)
</syntaxhighlight>
 
== Variable Zahl Parameter in Methode: Map ==
<syntaxhighlight lang="python">
# numbers ist eine Liste:
def show(**params):
    result = 0
    for name,value in params.items():
        print(f'{name}: {value}')
 
# function call with 3 arguments
show(jonny="admin", berta="user")
</syntaxhighlight>
 
== Reflection ==
<syntaxhighlight lang="python">
class A:
  def __init__(self):
    self._a = 0
  def asString(self):
    return 'A'
a = A()
assertTrue(hasattr(a, '_a'));
assertTrue(hasattr(a, 'asString'));
assertFalse(hasattr(a, 'b'));
</syntaxhighlight>
 
== Type Hints ==
<syntaxhighlight lang="python">
from typing import List, Sequence, Mapping
Vector = list[float]
Vector = list[float]
def sqr(x: float) -> float:
def sqr(x: float) -> float:
   return x*x
   return x*x
def first(items: Sequence[str]) -> str:
  return items[0]
def printName(name: str) -> None:
def printName(name: str) -> None:
   print(name);
   print(name);
</pre>
def evalMap(map: Mapping[int, str]):
  return map[3] == 'Hello'
</syntaxhighlight>


== Aufruf Superclass-Konstruktor ==
== Aufruf Superclass-Konstruktor ==
<pre>class B (A):
<syntaxhighlight lang="python">class B (A):
   def __init__(self, a):
   def __init__(self, a):
     A.__init__(self, a)
     A.__init__(self, a)
   def asString(self):
   def asString(self):
     return 'B: ' + super().asString
     return 'B: ' + super().asString
</pre>
</syntaxhighlight>


== Abstrakte Klasse ==
== Abstrakte Klasse ==
<pre>class A:
<syntaxhighlight lang="python">class A:


@abstractmethod
@abstractmethod
def process(self):
def process(self):
   pass
   pass
</pre>
</syntaxhighlight>


== Verschachtelte Methoden ==
== Verschachtelte Methoden ==
<pre>
<syntaxhighlight lang="python">
class Example:
class Example:
   def scan(self, file):
   def scan(self, file):
Zeile 258: Zeile 375:
       def _error(msg):
       def _error(msg):
         print("line {}: {}\n{}".format(lineNo, msg, line)
         print("line {}: {}\n{}".format(lineNo, msg, line)
</pre>       
</syntaxhighlight>       
          
          


Zeile 264: Zeile 381:
Damit eine Klasse mit "x in classInstance" angesprochen werden kann, muss es einen Iterator geben.
Damit eine Klasse mit "x in classInstance" angesprochen werden kann, muss es einen Iterator geben.
Im Beispiel wird dies in einer Klasse zusammengefasst:__iter__() liefert als Iterator sich selbst und __next__() implementiert diesen Iterator:
Im Beispiel wird dies in einer Klasse zusammengefasst:__iter__() liefert als Iterator sich selbst und __next__() implementiert diesen Iterator:
<pre>
<syntaxhighlight lang="python">
class Example:
class Example:
   def __init__():
   def __init__():
Zeile 280: Zeile 397:
   def next():
   def next():
     return self.__next__()
     return self.__next__()
</pre>
</syntaxhighlight>


== Generator ==
== Generator ==
* einfach mindestens ein "yield <value>" in die Funktion einfügen
* einfach mindestens ein "yield <value>" in die Funktion einfügen
* Bei Rekursion: yield from <method_call>
* Bei Rekursion: yield from <method_call>
<pre>def nextFile(directory)
<syntaxhighlight lang="python">def nextFile(directory)
  for node in os.listdir(directory):
  for node in os.listdir(directory):
   full = directory + os.sep + node
   full = directory + os.sep + node
Zeile 291: Zeile 408:
   if os.path.isdir(full):
   if os.path.isdir(full):
     yield from nextFile(full)
     yield from nextFile(full)
</pre>
</syntaxhighlight>


== Unittests ==
== Unittests ==
<pre>
<syntaxhighlight lang="python">
import unittest
import unittest
import sim_parser as sim
import sim_parser as sim
Zeile 308: Zeile 425:
if __name__ == "__main__":  
if __name__ == "__main__":  
     unittest.main()
     unittest.main()
</pre>
</syntaxhighlight>


== ArgParse ==
== ArgParse ==

Aktuelle Version vom 29. April 2024, 08:56 Uhr

Links[Bearbeiten]

Exception[Bearbeiten]

try:
   raise Exception("not allowed")
except ValueError as error:
   print('value error: ' + repr(error))
except SyntaxError as error:
   print('syntax error: ' + repr(error))
else:
    raise Exception("unknown")
try:
   doit()
finally:
   closeIt()

Regular Expression[Bearbeiten]

import re
rexpr = re.compile(r"([\da-z]+)")
match = rexpr.match(line)
if match != None:
   number = (int) rexpr.group(1)
# Replacement:
regex = re.compile(r"A\d+", re.IGNORECASE)
for line in some_file:
    other = regex.sub('<Id>', line)
# Replacement mit Referenzen:
s = 'aaa@xxx.com bbb@yyy.net ccc@zzz.org'
re.sub('([a-z]+)@([a-z]+)', r'\2@\1', s)

Datentypen[Bearbeiten]

String[Bearbeiten]

  • "x" und 'x' sind gleichwertig

Formatierung[Bearbeiten]

  • f-String
# Gleitpunktzahl mit 3 Stellen ausgeben:
f'{self.floatValue:.3f}'
# 2-stellig mit führender 0 ausgeben:
f'{sec//3600}:{sec%3600//60:02}:{sec%60:02}'
# String linksbündig:
f'{data:<10}'
# String rechtsbündig:
f'{data:>10}'
  • str.format()
"{:3.7f} {:s} {:07d}".format(3.14, "hello", 100)
"{0:d} / {0:x}".format(714)
"{}-{}: {}".format('abc.txt', 9, 7.99)
precision=2
'{:.Pf}'.replace('P', str(precision)).format(value)
  • Bytes -> String: b'data'.decode("utf-8")
  • String -> Bytes: "string".encode("utf-8")
  • capitalize() count() endswith() find() index()
  • isalnum() isalpha() isascii() isdecimal() isidentifier() islower() isnumeric() isprintable() isspace() isupper()
  • join() partition() rfind() rindex() rpartition() rsplit() split() splitlines() startswith()
  • strip() swapcase() title() translate() upper() zfill()

Bytes[Bearbeiten]

text = b"abcde".decode("utf-8") 
binary = "abc123".encode("utf-8")

Container (List)[Bearbeiten]

  • List: ['a', 1]; x[1] = 5; x.insert(0, 'firstItem'); x.remove('a'); ix=x.index('a'); del x[0];
    • x.append(99)
    • list1 = list1 + list2
  • Tupel: t = ('a', 1); l = list(t)
  • list2 = [x for x in range(3)]
  • contains99 = 99 in x

Dictionary[Bearbeiten]

x = { 'key' : 'val', 'xyz': 3 }
x['key'] = value
del x['key'];
contains = 'key' in x and 'key2' not in x
size = len(x)
for key, value in x.items():
  print(key, value)
for key in x:
  print key
  • x.itervalues()
  • x.setdefault(key[, value]): setzt Wert nur, wenn noch nicht gesetzt
  • x.keys(), x.values()
  • x.copy(): flache Kopie
  • x.update(dict): addiert dict zu x

Mengen[Bearbeiten]

s = {3, 'sjoerd'}
s = {c for c in 'abracadabra' if c not in 'abc'}
assertEquals(s, {'d', 'r'})
iterable = ['y', 3];
s = set(iterable) ; 
f = frozenset(iterable)
s.add(9)
s.remove(9) 
for elem in s:
  print elem
size = len(s)
contains = 3 in s and 4 not in s
intersection = s & f
union = s | f
isPartOf = s <= f
diff = s - f

Datum/Zeit[Bearbeiten]

import datetime, time
# ab hour optional:
date1 = datetime.datetime(2019, 4, 1, 22, 44, 12, 123456)
timeX = date1.timestamp() # float, sec since epoc
formatted = date1.strftime('%Y.%m.%dT%H:%M:%S')
now = datetime.datetime.now()
daylySeconds = (now.time().hour*60+now.time().minute)*60+now.time().second
yesterday = datetime.datetime.fromtimestamp(time.time() - 24*3600)
firstOfMonth = date1.replace(day=1)
asStringMicroseconds = date1.strftime('%Y.%m.%dT%H:%M:%S.%f dayOfTheWeek (e.g. "Sun"): %a')
weekNo = date1.strftime('%W')
# returns e.g. '08'
date2 = time.time()
date3 = time.localtime(date2)
date4 = time.strftime('%Y.%m.%d-%H:%M:%S.%f dayOfTheWeek: %w', date3)
dateXStr = time.strftime('%Y.%m.%d-%H:%M:%S.%f dayOfTheWeek: %w', time.localtime(timeX))
# Scannen aus Text:
date5 = datetime.datetime.strptime("30 Nov 00", "%d %b %y")
timeTuple = time.strptime("30 Nov 00", "%d %b %y")
# mktime interpretiert lokale Zeit!
time2 = time.mktime(timeTuple)
#  calendar.timegm()¶ interpretiert GM-Time
time3 = calendar.timegm(timeTuple)
date5 = datetime.datetime.fromtimestamp(time.time() - 86400));

# Zeitdifferenz 

date = date + datetime.timedelta(days=50, seconds=27, microseconds=10, milliseconds=29000, minutes=5, hours=8, weeks=2)
diffSec = (date1 - date2).total_seconds()
diffDays = (date1 - date2).days

Leistungsmessung[Bearbeiten]

import timeit
body = '''text = 'abcdefg'
s = list(text)
s[6] = 'W'
''.join(s)
'''
print(timeit.timeit(body, number=1000000))

Enum[Bearbeiten]

from enum import Enum
class TokenType(Enum):
  digit = 1 ; string = 2 ; id = 3 ; operator = 4

x = TokenType.id
for item in TokenType:
  print(item.name)

Typcheck[Bearbeiten]

isStringOrSubclass = isinstance(aVariable, str)
isString = type(aVariable) is str
isList = type([1, 2]) is list
isDict = type({ 0:"a", 1:"b" }) is dict

Spezielle Methoden/Attribute[Bearbeiten]

  • Statische Methoden:
class X:
   # statische Variable
   _data = []
   @staticmethod
   def add(item):
      X._data.append(item)

X.add("new")
  • Feststellen, ob Attribut existiert: hasattr(instance, nameOfAttribute)
  • dynamischer Code:
exec 'import ' + module
  • Vollständige Kopie (deep copy):
import copy
x = [1, 2]
y = copy.deepcopy(x)
  • Superclass-Konstruktor:
class Parent:
   def __init__(self, name)
      self._name = name
class Child(Parent):
   def __init__(self, name):
      Parser.__init__(self, name)

Funktionale Programmierung[Bearbeiten]

import functools, math
array = [ 1, 9, 7, 5 ]
max = functools.reduce(lambda rc, item: item if item > rc else rc, array, -1E+100)
squares = list(map(lambda x: x*x, array))
squares2 = list(filter(lambda x: int(math.sqrt(x)) == math.sqrt(x), array))

Typische Situationen[Bearbeiten]

Division Integer[Bearbeiten]

pairs = count // 2


Objekte kopieren (Shallow/Deep Copy)[Bearbeiten]

import copy
a = [1, 2, 3]
b = copy.copy(a)
c = [a, [1, 2, 3]]
d = copy.deepcopy(c)
# Speziell bei Listen (shallow copy):
copied_list = original_list[:]


Sortieren[Bearbeiten]

a =["Joe", "Eve", "Bob", "alma", "Adam"]
a.sort()
# sort by a global function:
a.sort(key=str.lower)
# sort by a lambda function which calculates the sorting key:
a.sort(key=lambda x: x[2])
# 2-stufig: nach Länge absteigend, dann alphabetisch:
a.sort(key=lambda x: (-len(x), x))
# comparism function:
def mySort(a, b): return len(a) - len(b)
import functools
a.sort(key=functools.cmp_to_key(mySort))

Externes Programm aufrufen[Bearbeiten]

with supbprocess.popen([ '/usr/bin/wc', '-l', file ], stdout=subprocess.PIPE) as proc:
   count = int(proc.stdout.read().decode())

Dateien[Bearbeiten]

  • Lesen:
with open(self._filename, "r") as fp:
  for line in fp:
     print(line)
  # fp.close() ist implizit
  • Binärdatei:
with open(self._filename, "rb") as fp:
  data = fp.read(8000)
  while data:
     doIt(data)
     data = fp.read(8000)
  • Schreiben:
with open(self._filename, "w") as fp, open(self._input, "r") as fpInp:
  line = fpInp.read()
  fp.write(line);

Sprachbesonderheiten[Bearbeiten]

Variable Zahl Parameter in Methode: Liste[Bearbeiten]

# numbers ist eine Liste:
def find_sum(*numbers):
    result = 0
    for num in numbers:
        result = result + num
    
    print("Sum = ", result)

# function call with 3 arguments
find_sum(1, 2, 3)

Variable Zahl Parameter in Methode: Map[Bearbeiten]

# numbers ist eine Liste:
def show(**params):
    result = 0
    for name,value in params.items():
        print(f'{name}: {value}')

# function call with 3 arguments
show(jonny="admin", berta="user")

Reflection[Bearbeiten]

class A:
  def __init__(self):
    self._a = 0
  def asString(self):
    return 'A'
a = A()
assertTrue(hasattr(a, '_a'));
assertTrue(hasattr(a, 'asString'));
assertFalse(hasattr(a, 'b'));

Type Hints[Bearbeiten]

from typing import List, Sequence, Mapping
Vector = list[float]
def sqr(x: float) -> float:
  return x*x
def first(items: Sequence[str]) -> str:
  return items[0]
def printName(name: str) -> None:
  print(name);
def evalMap(map: Mapping[int, str]):
  return map[3] == 'Hello'

Aufruf Superclass-Konstruktor[Bearbeiten]

class B (A):
  def __init__(self, a):
    A.__init__(self, a)
  def asString(self):
    return 'B: ' + super().asString

Abstrakte Klasse[Bearbeiten]

class A:

@abstractmethod
def process(self):
  pass

Verschachtelte Methoden[Bearbeiten]

class Example:
  def scan(self, file):
     lineNo = 0
     for line in file:
       lineNo += 1
       if line.startswith('[':
           chapter = Chapter(line[1:-1])
       elif re.match(r'\w+='):
           var, value = line.split('=')
           chapter._vars[var] = value
       else:
           _error('invalid input')
      def _error(msg):
         print("line {}: {}\n{}".format(lineNo, msg, line)


Klasse als Sequenz[Bearbeiten]

Damit eine Klasse mit "x in classInstance" angesprochen werden kann, muss es einen Iterator geben. Im Beispiel wird dies in einer Klasse zusammengefasst:__iter__() liefert als Iterator sich selbst und __next__() implementiert diesen Iterator:

class Example:
  def __init__():
    self._nextItems = []
  def __iter__():
    self._nextItems = [1, 2, 3]
    return self
  def __next__():
    if len(self._nextItem) == 0:
      raise StopIteration
    else:
      rc = self._nextItems[0]
      del self._nextItems[0]
      return rc
  def next():
    return self.__next__()

Generator[Bearbeiten]

  • einfach mindestens ein "yield <value>" in die Funktion einfügen
  • Bei Rekursion: yield from <method_call>
def nextFile(directory)
 for node in os.listdir(directory):
  full = directory + os.sep + node
  yield full
  if os.path.isdir(full):
    yield from nextFile(full)

Unittests[Bearbeiten]

import unittest
import sim_parser as sim

class SimParserTest(unittest.TestCase):
    
    def testNextToken(self):
        parser = sim.SimParser()
        parser.setSource('''10 'abc' var12 +;
    ''')
        self.assertEqual(parser.token(0), sim.Number(10, True, 0, 0))

if __name__ == "__main__": 
    unittest.main()

ArgParse[Bearbeiten]

def main(argv=None): # IGNORE:C0111
    '''Command line options.'''
    if argv is None:
        argv = sys.argv
    program_name = os.path.basename(sys.argv[0])
    program_version = "v%s" % __version__
    program_build_date = str(__updated__)
    program_version_message = '%%(prog)s %s (%s)' % (program_version, program_build_date)
    program_shortdesc = __import__('__main__').__doc__.split("\n")[1]
    program_license = '''%s
  Created by Hamatoma on %s.
  Copyright 2022 Hamatoma. All rights reserved.

  Licensed under the Apache License 2.0
  http://www.apache.org/licenses/LICENSE-2.0

  Distributed on an "AS IS" basis without warranties
  or conditions of any kind, either express or implied.
USAGE
''' % (program_shortdesc, str(__date__))
    try:
        # Setup argument parser
        parser = ArgumentParser(description=program_license, formatter_class=RawDescriptionHelpFormatter)
        parser.add_argument('file', help="file to dump")
        parser.add_argument('-v', '--verbose', dest='verbose', action='count', help='set verbosity level [default: %(default)s]')
        parser.add_argument('-o', '--offset', dest='offset', help='offset of the output [default: %(default)s]', metavar='OFFSET', type=int, default=0)
        parser.add_argument('-l', '--length', dest='length', help='length of the output [default: %(default)s]', metavar='LENGTH', type=int, default=80 )
        parser.add_argument('-V', '--version', action='version', version=program_version_message)
        args = parser.parse_args(argv[1:])
        offset = args.offset
        length = args.length
        filename = args.file
        if not os.path.exists(filename):
            raise CLIError('not a file: ' + filename)
...
        return 0
    except KeyboardInterrupt:
        return 0
    except Exception as e:
        if DEBUG or TESTRUN:
            raise(e)
        indent = len(program_name) * " "
        sys.stderr.write(program_name + ": " + repr(e) + "\n")
        sys.stderr.write(indent + "  for help use --help")
        return 2
if __name__ == "__main__":
    sys.exit(main())