# When defining a function , The default parameter must follow the non default parameter , Otherwise, there will be a syntax error
>>> def func1(name='bob', age):
... pass
...
File "<stdin>", line 1
SyntaxError: non-default argument follows default argument
>>> def func1(name, age=20): # correct
... pass
>>> def func1(age,name='bob'): # correct , This means that when defining a function, those with default parameters should be placed after it .
... pass
...
>>> def func1(age=20,name): # Report errors , It should be in the back .
... pass
...
File "<stdin>", line 1
SyntaxError: non-default argument follows default argument
>>> def func1(name, age):
... print('%s is %s years old' % (name, age))
>>> func1('tom', 20) # correct -
tom is 20 years old
>>> func1(20, 'tom') # The grammar is correct , But the semantics are not right
20 is tom years old
>>> func1(age=20, name='tom') # correct -
tom is 20 years old
>>> func1(age=20, 'tom') # Grammar mistakes
File "<stdin>", line 1
SyntaxError: positional argument follows keyword argument
>>> func1(20, name='tom') # error ,name You get multiple values
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: func1() got multiple values for argument 'name'
>>> func1('tom', age=20) # correct -
tom is 20 years old
>>> def func1(*args):
... print(args)
...
>>> func1()
()
>>> func1('hao')
('hao',)
>>> func1('hao', 123, 'tom')
('hao', 123, 'tom')
>>> def func2(**kwargs):
... print(kwargs)
...
>>> func2()
{}
>>> func2(10)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: func2() takes 0 positional arguments but 1 was given
>>> func2(name='tom', age=20)
{'name': 'tom', 'age': 20}
>>> def func3(*args, **kwargs):
... print(args)
... print(kwargs)
...
>>> func3()
()
{}
>>> func3(10, 20, 30, name='tom', age=20)
(10, 20, 30)
{'name': 'tom', 'age': 20}
* Represents a split sequence
** Represents a split dictionary
>>> def add(a, b):
... return a + b
...
>>> nums = [10, 20]
>>> add(nums) # because nums It's just a parameter ,nums Pass to a,b You don't get the value
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: add() missing 1 required positional argument: 'b'
>>> add(*nums) # take nums Open , Pass values to, respectively a and b
30
>>> mydict = {'a': 100, 'b':200}
>>> add(**mydict) # ** Open a dictionary , amount to add(a=100, b=200)
300
practice : Simple addition and subtraction math game
5 + 5 = 10
Very Good!!!
Continue(y/n)? y
42 + 26 = 50
Wrong Answer!!!
42 + 26 = 55
Wrong Answer!!!
42 + 26 = 60
Wrong Answer!!!
42 + 26 = 68
Continue(y/n)? n
Bye-bye
The first method :
from random import randint, choice
def exam():
nums = [randint(1, 100) for i in range(2)]
nums.sort(reverse=True) # Descending order
op = choice('+-') # Randomly select the plus minus sign
# Figure out the right answer
if op == '+':
result = nums[0] + nums[1]
else:
result = nums[0] - nums[1]
# Let the user answer , Judge right or wrong
prompt = '%s %s %s = ' % (nums[0], op, nums[1])
counter = 0
while counter < 3:
try:
answer = int(input(prompt))
except: # You can catch all exceptions without specifying exceptions , But not recommended
print()
continue
if answer == result:
print(' excellent !!!')
break
print(' No !!!')
counter += 1
else:
print('%s%s' % (prompt, result))
def main():
" This function comes out first , Then ask the user if they want to continue "
while True:
exam()
# After removing the white space at both ends of the string , Take out the first character
try:
yn = input('Continue(y/n)? ').strip()[0]
except IndexError:
yn = 'y'
except (KeyboardInterrupt, EOFError):
yn = 'n'
if yn in 'nN':
print('\nBye-bye')
break
if __name__ == '__main__':
main()
The second method :
from random import randint, choice
def add(x, y):
return x + y
def sub(x, y):
return x - y
def exam():
cmds ={'+': add, '-': sub}
nums = [randint(1, 100) for i in range(2)]
nums.sort(reverse=True) # Descending order
op = choice('+-') # Randomly select the plus minus sign
# Figure out the right answer
result = cmds[op](*nums)
# Let the user answer , Judge right or wrong
prompt = '%s %s %s = ' % (nums[0], op, nums[1])
counter = 0
while counter < 3:
try:
answer = int(input(prompt))
except: # You can catch all exceptions without specifying exceptions , But not recommended
print()
continue
if answer == result:
print(' excellent !!!')
break
print(' No !!!')
counter += 1
else:
print('%s%s' % (prompt, result))
def main():
" This function comes out first , Then ask the user if they want to continue "
while True:
exam()
# After removing the white space at both ends of the string , Take out the first character
try:
yn = input('Continue(y/n)? ').strip()[0]
except IndexError:
yn = 'y'
except (KeyboardInterrupt, EOFError):
yn = 'n'
if yn in 'nN':
print('\nBye-bye')
break
if __name__ == '__main__':
main()
test :
$ python 2.py
26 + 9 = 2
No !!!
26 + 9 = 2
No !!!
26 + 9 = 2
No !!!
26 + 9 = 35
Continue(y/n)? y
52 - 3 = 49
excellent !!!
Continue(y/n)? skhdk # Any input can continue , As long as it's not nN, Because we write exception handling try sentence
84 + 79 = 22
No !!!
84 + 79 = 55
No !!!
84 + 79 = 55
No !!!
84 + 79 = 163
Continue(y/n)? n
Bye-bye
>>> def func1(x):
... return x + 10
...
>>> func1(2)
12
>>> add10 = lambda x: x + 10
>>> add10(2)
12
>>> from random import randint
>>> nums = [randint(1, 100) for i in range(10)]
>>> nums
[93, 2, 11, 70, 16, 23, 89, 17, 47, 91]
>>> def func1(x):
... return True if x > 50 else False
>>> list(filter(func1, nums))
[93, 70, 89, 91]
>>> list(filter(lambda x: True if x > 50 else False, nums))
[93, 70, 89, 91]
```
### map function
- For processing data
- Take two parameters
- The first argument is the function , For processing data
- The second parameter is the sequence , Each object in the sequence is used as an argument to the previous function
- Take each data in the sequence as an argument to the function , After processing, return to
>>> def func2(x):
... return x * 2
...
>>> list(map(func2, nums))
[186, 4, 22, 140, 32, 46, 178, 34, 94, 182]
>>> list(map(lambda x: x * 2, nums))
[186, 4, 22, 140, 32, 46, 178, 34, 94, 182]
>>> list(map(lambda x: x * 5,nums))
[265, 210, 95, 90, 170, 120, 455, 85, 220, 275]
# 1. Defined outside the function are global variables , Global variables are defined from the beginning to the end of the program , It's always available
>>> x = 10
>>> def func1():
... print(x)
...
>>> func1()
10
# 2. Variables defined inside a function are local variables , It's only visible inside the function
>>> def func2():
... y = 10
... print(y)
...
>>> func2()
10
>>> print(y)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
NameError: name 'y' is not defined
# 3. If local and global variables have the same name , Give priority to local , Local variables cover global variables
>>> def func3():
... x = 100
... print(x)
...
>>> func3()
100
>>> print(x)
10
# 4. If you need to change global variables locally , Make have global keyword
>>> def func4():
... global x
... x = 1000
... print(x)
...
>>> func4()
1000
>>> print(x)
1000
Transform existing functions , Fix some of its parameters , Generate a new function .
>>> def add(a, b, c, d, e):
... return a + b + c + d + e
...
>>> add(10, 20, 30, 40, 5)
105
>>> add(10, 20, 30, 40, 22)
122
>>> from functools import partial
>>> myadd = partial(add, 10, 20, 30, 40)
>>> myadd(10)
110
>>> myadd(5)
105
# int Accept base Specifies the base of the string
>>> int('11111111', base=2)
255
>>> int2 = partial(int, base=2) # reform int function , take 2 Turn into the system 10 Base number
>>> int2('11111111')
255
5!=5x4x3x2x1
5!=5x4!
5!=5x4x3!
5!=5x4x3x2!
5!=5x4x3x2x1!
1!=1
>>> def func(x):
... if x == 1:
... return 1
... return x * func(x - 1)
...
>>> func(5)
120
>>> func(6)
720
Quick sort
from random import randint
def qsort(seq):
if len(seq) < 2:
return seq
middle = seq[0]
smaller = []
larger = []
for data in seq[1:]:
if data >= middle:
larger.append(data)
else:
smaller.append(data)
return qsort(smaller) + [middle] + qsort(larger)
if __name__ == '__main__':
nums = [randint(1,100) for i in range(10)]
print(nums)
print(qsort(nums))
$ python 2.py
[31, 59, 24, 30, 20, 19, 23, 96, 38, 67] # Output nums Value
[19, 20, 23, 24, 30, 31, 38, 59, 67, 96] # Output qsort(nums) Sorted value
# Generator expressions have the same syntax as list parsing , Just use ()
>>> ips = ('192.168.1.%s' % i for i in range(1, 255))
>>> for ip in ips:
... print(ip)
# Using functions , adopt yield Returns the intermediate value many times
>>> def mygen():
... yield 100
... n = 10 + 20
... yield n
... yield 'hello world'
...
>>> mg = mygen()
>>> for i in mg:
... print(i)
...
100
30
hello world
Used to calculate the hash value . Hash values such as md5 / sha etc. , Commonly used for encryption password and file integrity verification .
>>> import hashlib
>>> m = hashlib.md5(b'123456')
>>> m.hexdigest()
'e10adc3949ba59abbe56e057f20f883e'
# If the amount of data is too large , You can create md5 After the object , One part at a time
>>> import hashlib
>>> m1 = hashlib.md5()
>>> m1.update(b'12')
>>> m1.update(b'34')
>>> m1.update(b'56')
>>> m1.hexdigest()
'e10adc3949ba59abbe56e057f20f883e'
# If the amount of data is too large , You can create md5 After the object , One part at a time
>>> m1 = hashlib.md5()
>>> m1.update(b'12')
>>> m1.update(b'34')
>>> m1.update(b'56')
>>> m1.hexdigest()
'e10adc3949ba59abbe56e057f20f883e'
>>> with open('/bin/ls', 'rb') as fobj:
... data = fobj.read()
...
>>> m = hashlib.md5(data)
>>> m.hexdigest()
'038a0a2d35a503d299a46096f6ff9890'
import hashlib
import sys
def check_md5(fname):
m = hashlib.md5()
with open(fname,'rb') as fobj:
while True:
data = fobj.read(4096)
if not data:
break
m.update(data)
return m.hexdigest()
if __name__ == '__main__':
print(check_md5(sys.argv[1]))
verification :
$ python 2.py /etc/hosts # In the calculation md5 It's worth it python Program files are directly followed by location parameters , That is, the file path
df8bdcf4591134e0fca820b7d07451c8
>>> import tarfile
# Compress
>>> tar = tarfile.open('/tmp/mytar.tar.gz', 'w:gz')
>>> tar.add('/etc/hosts')
>>> tar.add('/etc/security')
>>> tar.close()
# Unzip to /tmp/demo
>>> tar = tarfile.open('/tmp/mytar.tar.gz')
>>> tar.extractall(path='/tmp/demo/')
>>> tar.close()
$ python 2.py
$ ls /luo/
demo mytar.tar.gz
$ ll /luo/
drwxrwxr-x 3 student student 4096 8 month 8 17:43 demo
-rw-rw-r-- 1 student student 288 8 month 8 17:43 mytar.tar.gz
practice : Backup program
1. Need to support full and incremental backup
2. Perform a full backup on Monday
3. Do incremental backups at other times
4. Backup files need to be packaged as tar File and use gzip Format compression
import os
import tarfile
import hashlib
import pickle
from time import strftime
def check_md5(fname):
m = hashlib.md5()
with open(fname, 'rb') as fobj:
while True:
data = fobj.read(4096)
if not data:
break
m.update(data)
return m.hexdigest()
def full_backup(src, dst, md5file):
" A full backup requires packaging the directory and calculating the size of each file md5 value "
# Backup tar The file should have a backup directory name 、 Backup type 、 Time
fname = '%s_full_%s.tar.gz' % (os.path.basename(src), strftime('%Y%m%d'))
fname = os.path.join(dst, fname)
# Package the source directory
tar = tarfile.open(fname, 'w:gz')
tar.add(src)
tar.close()
# Calculate the... Of each file md5 value , Put it in the dictionary
md5dict = {}
for path, folders, files in os.walk(src):
for file in files:
key = os.path.join(path, file)
md5dict[key] = check_md5(key)
# adopt pickle Save the dictionary in a file permanently
with open(md5file, 'wb') as fobj:
pickle.dump(md5dict, fobj)
def incr_backup(src, dst, md5file):
" Incremental backup packages new files and changed files ; to update md5 File for subsequent comparison "
# Backup tar The file should have a backup directory name 、 Backup type 、 Time
fname = '%s_incr_%s.tar.gz' % (os.path.basename(src), strftime('%Y%m%d'))
fname = os.path.join(dst, fname)
# Calculate the... Of each file md5 value , Put it in the dictionary
md5dict = {}
for path, folders, files in os.walk(src):
for file in files:
key = os.path.join(path, file)
md5dict[key] = check_md5(key)
# Take out the day before md5 value
with open(md5file, 'rb') as fobj:
old_md5 = pickle.load(fobj)
# Package new files and changed files
tar = tarfile.open(fname, 'w:gz')
for key in md5dict:
if old_md5.get(key) != md5dict[key]:
tar.add(key)
tar.close()
# to update md5 Dictionary file
with open(md5file, 'wb') as fobj:
pickle.dump(md5dict, fobj)
if __name__ == '__main__':
src = '/tmp/demo/security'
dst = '/tmp/backup'
md5file = '/tmp/backup/md5.data'
if not os.path.isdir(dst):
os.mkdir(dst)
if strftime('%a') == 'Mon':
full_backup(src, dst, md5file)
else:
incr_backup(src, dst, md5file)
>>> list(os.walk('/etc/security'))
[('/etc/security', ['console.apps', 'console.perms.d', 'limits.d', 'namespace.d'], ['access.conf', 'chroot.conf', 'console.handlers', 'console.perms', 'group.conf', 'limits.conf', 'namespace.conf', 'namespace.init', 'opasswd', 'pam_env.conf', 'sepermit.conf', 'time.conf', 'pwquality.conf']), ('/etc/security/console.apps', [], ['config-util', 'xserver', 'liveinst', 'setup']), ('/etc/security/console.perms.d', [], []), ('/etc/security/limits.d', [], ['20-nproc.conf']), ('/etc/security/namespace.d', [], [])]
>>> result = list(os.walk('/etc/security'))
>>> len(result)
5
>>> result[0]
('/etc/security', ['console.apps', 'console.perms.d', 'limits.d', 'namespace.d'], ['access.conf', 'chroot.conf', 'console.handlers', 'console.perms', 'group.conf', 'limits.conf', 'namespace.conf', 'namespace.init', 'opasswd', 'pam_env.conf', 'sepermit.conf', 'time.conf', 'pwquality.conf'])
>>> result[1]
('/etc/security/console.apps', [], ['config-util', 'xserver', 'liveinst', 'setup'])
>>> result[2]
('/etc/security/console.perms.d', [], [])
>>> for path, folers, files in os.walk('/etc/security'):
... for file in files:
... os.path.join(path, file)