Python: Unterschied zwischen den Versionen

Aus Info-Theke
Zur Navigation springen Zur Suche springen
Zeile 1: Zeile 1:
[[Kategorie:Sprache]]
[[Kategorie:Sprache]]
= Exception =
= Exception =
<pre>
<syntaxhighlight lang="python">
try:
try:
   raise Exception("not allowed")
   raise Exception("not allowed")
Zeile 14: Zeile 14:
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 23:
if match != None:
if match != None:
   number = (int) rexpr.group(1)
   number = (int) rexpr.group(1)
</pre>
</syntaxhighlight>


= Datentypen =
= Datentypen =
Zeile 66: Zeile 66:


== Dictionary==
== Dictionary==
<pre>
<syntaxhighlight lang="python">
x = { 'key' : 'val', 'xyz': 3 }
x = { 'key' : 'val', 'xyz': 3 }
x['key'] = value
x['key'] = value
Zeile 76: Zeile 76:
for key in x.iterkeys():
for key in x.iterkeys():
   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 84: Zeile 84:


== Mengen ==
== Mengen ==
<pre>
<syntaxhighlight lang="python">
s = set(['y', 3]) ; f = frozenset(['y', 3])  
s = set(['y', 3]) ; f = frozenset(['y', 3])  
for elem in s:
for elem in s:
Zeile 94: Zeile 94:
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 127: Zeile 128:
diffSec = (date1 - date2).total_seconds()
diffSec = (date1 - date2).total_seconds()
diffDays = (date1 - date2).days
diffDays = (date1 - date2).days
</pre>
</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
Zeile 137: Zeile 139:
for item in TokenType:
for item in TokenType:
   print(item.name)
   print(item.name)
</pre>
</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 158: Zeile 160:


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 178: Zeile 180:
   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 187: Zeile 189:
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 =
Zeile 213: Zeile 215:


== 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>
* 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 =
== Type Hints ==
== Type Hints ==
<pre>
<syntaxhighlight lang="python">
from typing import Sequence
from typing import Sequence
Vector = list[float]
Vector = list[float]
Zeile 244: Zeile 246:
def printName(name: str) -> None:
def printName(name: str) -> None:
   print(name);
   print(name);
</pre>
</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 278: Zeile 280:
       def _error(msg):
       def _error(msg):
         print("line {}: {}\n{}".format(lineNo, msg, line)
         print("line {}: {}\n{}".format(lineNo, msg, line)
</pre>       
</syntaxhighlight>       
          
          


Zeile 284: Zeile 286:
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 300: Zeile 302:
   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 311: Zeile 313:
   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 328: Zeile 330:
if __name__ == "__main__":  
if __name__ == "__main__":  
     unittest.main()
     unittest.main()
</pre>
</syntaxhighlight>


== ArgParse ==
== ArgParse ==

Version vom 26. Oktober 2022, 06:58 Uhr

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())