Python
Exception
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
import re rexpr = re.compile(r"([\da-z]+)") match = rexpr.match(line) if match != None: number = (int) rexpr.group(1)
Datentypen
String
- "x" und 'x' sind gleichwertig
Formatierung
- 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}'
- 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
text = b"abcde".decode("utf-8")
binary = "abc123".encode("utf-8")
Container (List)
- 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
x = { 'key' : 'val', 'xyz': 3 } x['key'] = value del x['key']; contains = 'key' in x and 'key2' not in x size = len(x) for pair in x.iteritems(): key = pair[0] for key in x.iterkeys(): 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
s = set(['y', 3]) ; f = frozenset(['y', 3]) 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
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
Enum
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
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
- 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
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
Objekte kopieren (Shallow/Deep Copy)
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
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])
Externes Programm aufrufen
with supbprocess.popen([ '/usr/bin/wc', '-l', file ], stdout=subprocess.PIPE) as proc: count = int(proc.stdout.read().decode())
Dateien
- Lesen:
with open(self._filename, "r") as fp: for line in fp: print(line) # fp.close() ist implizit
- Schreiben:
with open(self._filename, "w") as fp, open(self._input, "r") as fpInp: line = fpInp.read() fp.write(line);
Sprachbesonderheiten
Type Hints
from typing import Sequence 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);
Aufruf Superclass-Konstruktor
class B (A): def __init__(self, a): A.__init__(self, a) def asString(self): return 'B: ' + super().asString
Abstrakte Klasse
class A: @abstractmethod def process(self): pass
Verschachtelte Methoden
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
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
- 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
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
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())