【Python之路Day4】基础篇
今日目录:
1. Python内置函数
2. 装饰器
一. Python内置函数
内置函数主要是使用比较频繁的或者是元操作,所以Python通过内置函数的方式提供给开发者,如下表:
下面现阶段只介绍一些目前学到的知识,涉及到面向对象的内置函数等先不讨论,待下次再续;
abs() 取绝对值
# 取绝对值,和数值内部的内置方法__abs__()是一样的 >>> a = -130 >>> abs(a) 130 >>> a.__abs__() 130 >>> b = 20 >>> abs(b) 20 >>> b.__abs__() 20
all() 所有为真,则为真,否则为假
#所有为真,则为真 >>> c = ['a','b','c',0,None,False,] >>> all(c) False >>> d = ['a','b','c',] >>> all(d) True
any() 至少有一个为真,就为真,否则为假
>>> c = ['a','b','c',0,None,False,] >>> all(c) False >>> d = ['a','b','c',] >>> all(d) True >>> any(c) True >>> any(d) True #e的元素有False,None,但是有个1位真,所以结果为真 >>> e = [False,None,1] >>> any(e) True
ascii() 和repr()一样,返回一个对象的可打印的字符串表示方式,如果遇到非ASCII字符串,使用\\x, \\u 或者\\U表示,与Python2李的repr()等效;
#赋值a为一大串字符串,查看ascii之后的显示 >>> a = 'I am daniel\n%^%@#$^*@#$Age: 18\nSex: M' >>> ascii(a) "'I am daniel\\n%^%@#$^*@#$Age: 18\\nSex: M'" #再次使用中文(非Ascii码),出来好多\\u之类的 >>> b = '我是谁?' >>> ascii(b) "'\\u6211\\u662f\\u8c01\\uff1f'"
callable() 判断函数是否可以被调用,如果可以返回True,否则返回False
#先定义一个函数 >>> def f1(): ... print('balabala') ... >>> result = callable(f1) #如果可以调用,返回True,否则返回值为False >>> print(result) True #如下f2是一个字符串,执行后返回false >>> f2 = 'name' >>> callable(f2) False
bin() 将十进制数转换为二进制表示
#0b代表binary >>> i = 20 >>> bin(i) '0b10100'
hex() 将十进制的数值转换为十六进制
>>> i = 28 >>> hex(i) '0x1c'
oct() 将十进制数值转换为8进制
>>> oct(i) '0o34' #0后面是o,表示8进制
bool() 返回给定元素的布尔值
#可以看出所有空值都是False >>> bool(False) False >>> bool(0) False >>> bool('') False >>> bool(None) False >>> bool([]) False >>> bool({}) False >>> bool(()) False >>> bool(1) True
bytes() str() 各种编码转换
Python3中对文本(字符串)和二进制数据做了比较清晰的区分。文本总是使用unicode,由str类型表示,二进制数据用bytes类型表示。
Python3不会以任何隐式的方式混用str和bytes,因此这两者区分特别清晰。所以,不能拼接字符串和字节包,也无法在字节包里搜索字符串,也不能将字符串传入参数为字符包的函数等等。
#设置一个原始字符串 >>> s1 = '[1,2,3,4,5,6,]' >>> type(s1) <class 'str'> # 设置一个bytes数据类型 >>> s2 = bytes('[1,2,3,4,5,6,]','ascii') >>> type(s2) <class 'bytes'> >>> s1 '[1,2,3,4,5,6,]' >>> s2 b'[1,2,3,4,5,6,]' #按utf-8编码,转换成bytes >>> s1_bytes = s1.encode(encoding='utf-8') >>> type(s1_bytes) <class 'bytes'> >>> s1_bytes b'[1,2,3,4,5,6,]' #按照GB2312编码格式转换s1 >>> >>> s1_gb2312 = s1.encode(encoding='gb2312') >>> s1_gb2312 b'[1,2,3,4,5,6,]' >>> type(s1_gb2312) <class 'bytes'> #解码成string,默认为空 >>> s1_string = s1_bytes s1_bytes >>> s1_string = s1_bytes.decode() >>> s1_string '[1,2,3,4,5,6,]' >>> type(s1_string) <class 'str'> #也可以使用gb2312的方式解码成gb2312的string >>> s1_string_gb2312 = s1_gb2312.decode('gb2312') >>> s1_string_gb2312 '[1,2,3,4,5,6,]' >>> type(s1_string_gb2312) <class 'str'> #也可以使用下面转换方式: #创建bytes >>> s3 = b'www.dbq168.com' >>> type(s3) <class 'bytes'> >>> s3 b'www.dbq168.com' #创建str >>> s4 = 'www.dbq168.com' >>> type(s4) <class 'str'> >>> s4 'www.dbq168.com' #str转换成bytes >>> bytes(s4,encoding='utf-8') b'www.dbq168.com' #bytes转到str >>> str(s3,encoding = 'utf-8') 'www.dbq168.com' # >>> type(s3) <class 'bytes'> >>> type(s4) <class 'str'> #str to bytes >>> str.encode(s4) b'www.dbq168.com' #bytes to str >>> bytes.decode(s3) 'www.dbq168.com'
bytearray() 返回一个bytes数组,bytearray类型是一个可变的序列,并且序列中的元素取值范围是0~256之间;
#可迭代类型,元素范围不能超过256,否则报错 >>> d = bytearray((333,222,251,288)) Traceback (most recent call last): File "<stdin>", line 1, in <module> ValueError: byte must be in range(0, 256) >>> c = bytearray([1,2,3,4,]) >>> c[0] 1 >>> c[1] 2 >>> c[2] 3 >>> c[3] 4 >>> c bytearray(b'\x01\x02\x03\x04') #传入的是字符串,则按照指定的encoding将字符串转为字符序列; >>> a = 'www.dbq.com, blog.dbq.com' >>> b = bytearray(a,encoding='utf-8') >>> b bytearray(b'www.dbq.com, blog.dbq.com') >>> b[0] 119 >>> b[1] 119
chr() 和 ord()
chr 返回一个元素在ASCII表里对应的关系的字符串,如str(65)返回的是大写字母“A“ ,反查是 ord()
#这哥俩就是一个查询,一个反查询 >>> chr(65) 'A' >>> chr(68) 'D' >>> chr(69) 'E' >>> chr(77) 'M' >>> chr(12) '\x0c' >>> chr(33) '!' >>> chr(45) '-' >>> chr(90) 'Z' >>> chr(933) 'Υ' >>> chr(93) ']' >>> ord(']') 93 >>> ord('Z') 90 >>> ord('Z')
对照ASCII码对照表,完成一个小需求,比如现在用的比较多的验证码程序(非12306,哈哈),如何生成一个字母带数字组合的6位随机码?
#分析下需求,可以用个for循环,每次调用random模块的randrange方法,让其从65-90之间任取一个随机数, #然后用chr找到在ascii对照表中的大写字母,追加到列表中,而后把列表拼接起来即可!如下面代码: #!/usr/bin/env python3 # -*- coding: utf-8 -*- # Author: DBQ(Du Baoqiang) import random l1 = [] for i in range(6): num = random.randrange(65,90) num = chr(num) l1.append(num) result = "".join(l1) print(result) #增强版,在生成一个随机数,把随机数字插入到列表中去: import random l1 = [] for i in range(6): I = random.randrange(0,6) num = random.randrange(65,90) num = chr(num) if i == I or I == 3 or I == 4: l1.append(str(I)) else: l1.append(num) result = "".join(l1) print(result)
divmod() 相除,返回商和余数,返回值是一个元组
#使用场景,比如说总共有102个文章,现在要分页显示,每页只显示15个文章,就可以基于这个来做,而后对元组内的商和余数进行判断等等后续操作 >>> a = 102 >>> divmod(a,15) (6, 12)
max() 取最大值
>>> l1 = [11,22,33,44,55,66,666,] >>> max(l1) 666 #当然Python3中字符串和数字是不能比较的,否则会报错 >>> l1 = [11,22,33,44,55,66,666,'a'] >>> max(l1) Traceback (most recent call last): File "<stdin>", line 1, in <module> TypeError: unorderable types: str() > int()
min() 取最小值
>>> l1 = [11,22,33,44,55,66,666] >>> min(l1) 11
sum() 求和
>>> l1 = [11,22,33,44,55,66,666] >>> sum(l1) 897
dict() 字典函数
>>> d1 = dict(name='daniel',age=18) >>> d1 {'name': 'daniel', 'age': 18}
list() 列表函数
>>> l1 = list([1,2,3,4,5,]) >>> type(l1) <class 'list'> >>> l1 [1, 2, 3, 4, 5]
tuple() 元组
>>> t1 = tuple((1,2,3,4,5)) >>> type(t1) <class 'tuple'> >>> t1 (1, 2, 3, 4, 5) >>> t1. t1.__add__( t1.__ge__( t1.__le__( t1.__repr__( t1.__class__( t1.__getattribute__( t1.__len__( t1.__rmul__( t1.__contains__( t1.__getitem__( t1.__lt__( t1.__setattr__( t1.__delattr__( t1.__getnewargs__( t1.__mul__( t1.__sizeof__( t1.__dir__( t1.__gt__( t1.__ne__( t1.__str__( t1.__doc__ t1.__hash__( t1.__new__( t1.__subclasshook__( t1.__eq__( t1.__init__( t1.__reduce__( t1.count( t1.__format__( t1.__iter__( t1.__reduce_ex__( t1.index(
str() 字符串
>>> name = str('daniel') >>> type(str) <class 'type'> >>> name 'daniel' >>> name. name.__add__( name.__mod__( name.expandtabs( name.lstrip( name.__class__( name.__mul__( name.find( name.maketrans( name.__contains__( name.__ne__( name.format( name.partition( name.__delattr__( name.__new__( name.format_map( name.replace( name.__dir__( name.__reduce__( name.index( name.rfind( name.__doc__ name.__reduce_ex__( name.isalnum( name.rindex( name.__eq__( name.__repr__( name.isalpha( name.rjust( name.__format__( name.__rmod__( name.isdecimal( name.rpartition( name.__ge__( name.__rmul__( name.isdigit( name.rsplit( name.__getattribute__( name.__setattr__( name.isidentifier( name.rstrip( name.__getitem__( name.__sizeof__( name.islower( name.split( name.__getnewargs__( name.__str__( name.isnumeric( name.splitlines( name.__gt__( name.__subclasshook__( name.isprintable( name.startswith( name.__hash__( name.capitalize( name.isspace( name.strip( name.__init__( name.casefold( name.istitle( name.swapcase( name.__iter__( name.center( name.isupper( name.title( name.__le__( name.count( name.join( name.translate( name.__len__( name.encode( name.ljust( name.upper( name.__lt__( name.endswith( name.lower( name.zfill(
int() 整数
>>> i1 = 18 >>> type(i1) <class 'int'> >>> i2 = int(19) >>> type(i2) <class 'int'> #创建完成后就拥有了整数所有的方法 >>> i2. i2.__abs__( i2.__gt__( i2.__rand__( i2.__sizeof__( i2.__add__( i2.__hash__( i2.__rdivmod__( i2.__str__( i2.__and__( i2.__index__( i2.__reduce__( i2.__sub__( i2.__bool__( i2.__init__( i2.__reduce_ex__( i2.__subclasshook__( i2.__ceil__( i2.__int__( i2.__repr__( i2.__truediv__( i2.__class__( i2.__invert__( i2.__rfloordiv__( i2.__trunc__( i2.__delattr__( i2.__le__( i2.__rlshift__( i2.__xor__( i2.__dir__( i2.__lshift__( i2.__rmod__( i2.bit_length( i2.__divmod__( i2.__lt__( i2.__rmul__( i2.conjugate( i2.__doc__ i2.__mod__( i2.__ror__( i2.denominator i2.__eq__( i2.__mul__( i2.__round__( i2.from_bytes( i2.__float__( i2.__ne__( i2.__rpow__( i2.imag i2.__floor__( i2.__neg__( i2.__rrshift__( i2.numerator i2.__floordiv__( i2.__new__( i2.__rshift__( i2.real i2.__format__( i2.__or__( i2.__rsub__( i2.to_bytes( i2.__ge__( i2.__pos__( i2.__rtruediv__( i2.__getattribute__( i2.__pow__( i2.__rxor__( i2.__getnewargs__( i2.__radd__( i2.__setattr__(
dir() 获取一个类提供的功能
>>> dir(d1) ['__class__', '__contains__', '__delattr__', '__delitem__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__getitem__', '__gt__', '__hash__', '__init__', '__iter__', '__le__', '__len__', '__lt__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__setitem__', '__sizeof__', '__str__', '__subclasshook__', 'clear', 'copy', 'fromkeys', 'get', 'items', 'keys', 'pop', 'popitem', 'setdefault', 'update', 'values']
help() 查看详细的帮助
Help on dict object: class dict(object) | dict() -> new empty dictionary | dict(mapping) -> new dictionary initialized from a mapping object's | (key, value) pairs | dict(iterable) -> new dictionary initialized as if via: | d = {} | for k, v in iterable: | d[k] = v | dict(**kwargs) -> new dictionary initialized with the name=value pairs | in the keyword argument list. For example: dict(one=1, two=2) | | Methods defined here: | | __contains__(self, key, /) | True if D has a key k, else False. | | __delitem__(self, key, /) | Delete self[key]. | | __eq__(self, value, /) | Return self==value. | | __ge__(self, value, /) | Return self>=value. 。。。。。
enumerate() 枚举元素,打印出索引和值
>>> for index,value in enumerate(d1.keys()): ... print(index,value) ... 0 name 1 age
compile() 把字符串编译成Python代码,而后调用exec执行
exec() 执行,比eval要牛逼,因为exec可以执行任何Python代码,但eval只能执行表达式;但有个缺陷是eval有返回值,而exec没有。
exec可以执行compile编译过的,也可以接受代码执行。
eval() 执行,把接受的字符串当做一个表达式,把代码编译成一行的表达式;
#定义一个字符串 >>> str1 = 'print("hello world")' >>> str1 'print("hello world")' #编译成python代码 >>> result = compile(str1,'<string>','exec') >>> print(result) <code object <module> at 0x1019e4db0, file "<string>", line 1> 调用exec执行 >>> exec(result) hello world >>> eval(result) hello world >>> r1 = exec(result) hello world >>> print(r1) None >>> r2 = eval(result) hello world >>> print(r2) #exec和eval都可以直接调用执行 >>> str1 'print("hello world")' >>> eval(str1) hello world >>> exec(str1) hello world
filter() 筛选,内部循环第二个参数,让每一个元素执行,如果值返回为True,表示元素合法,将元素添加到结果中,否则不做操作;
map() 不对函数返回值进行判断,直接将返回值添加到结果中;
比如现在有个需求,有一个列表l1 = [11,22,33,55,22,223,4452,886,223,258,664,198,] 现在需要找出里面大于100的元素,让我来实现,一下子想到的肯定是for循环整个列表,然后比较,再追加到一个新列表中去,最后不就出来了么?哈哈,这不是学新东西么,用filter可以方便的解决这个需求:
l1 = [11,22,33,55,22,223,4452,886,223,258,664,198,] #定一个函数,接受形参,如大大于100,return True def f1(num): if num > 100: return True #使用filter把l1赋值给f1,如果True的话,会把l1的元素赋值给result,否则不做处理; result = filter(f1,l1) print(list(result))
但是这么看有点不爽,简单点,lambda表达式:
l1 = [11,22,33,55,22,223,4452,886,223,258,664,198,] result = filter(lambda f1: f1>100,l1) print(list(result))
map的例子简单来一个,比如说想把列表l1中的所有元素值+100,那么来了:
l1 = [11,22,33,55,22,223,4452,886,223,258,664,198,] result = map(lambda f1: f1+100,l1) print(list(result))
float() 浮点数函数
>>> f1 = float(3.1415926) >>> f1 3.1415926 #下面这些方法在第一天、第二天的内容里已经详细说明并举例了 >>> type(f1) <class 'float'> >>> f1. f1.__abs__( f1.__getformat__( f1.__pow__( f1.__setformat__( f1.__add__( f1.__getnewargs__( f1.__radd__( f1.__sizeof__( f1.__bool__( f1.__gt__( f1.__rdivmod__( f1.__str__( f1.__class__( f1.__hash__( f1.__reduce__( f1.__sub__( f1.__delattr__( f1.__init__( f1.__reduce_ex__( f1.__subclasshook__( f1.__dir__( f1.__int__( f1.__repr__( f1.__truediv__( f1.__divmod__( f1.__le__( f1.__rfloordiv__( f1.__trunc__( f1.__doc__ f1.__lt__( f1.__rmod__( f1.as_integer_ratio( f1.__eq__( f1.__mod__( f1.__rmul__( f1.conjugate( f1.__float__( f1.__mul__( f1.__round__( f1.fromhex( f1.__floordiv__( f1.__ne__( f1.__rpow__( f1.hex( f1.__format__( f1.__neg__( f1.__rsub__( f1.imag f1.__ge__( f1.__new__( f1.__rtruediv__( f1.is_integer( f1.__getattribute__( f1.__pos__( f1.__setattr__( f1.real
format() 格式化输出字符串用,大力推荐使用format来格式化输出字符串,总之好处一大堆啦,真想看明白为啥推荐,那就点我呀点我呀
>>> name = 'daniel' >>> age = 18 >>> '%s %s' %(name,age) 'daniel 18' >>> '{} {}'.format(name,age) 'daniel 18' #调换位置 >>> '{1} {0}'.format(name,age) '18 daniel' #随意组合: >>> '{1} {0} {job}'.format(name,age,job='IT') '18 daniel IT' #靠左靠右: #靠右 print('%10s' %('test')) print('{:>10}'.format('test')) #左 print('%-10s' %('test')) print('{:10}'.format('test')) #居中 print('{:^10}'.format('test'))
frozenset() 不可变集合
set() 可变集合
python中有两种集合类型,set和frozenset。set是可变的,有add(), remove(), difference()等等方法,但是既然是可变的,那么set就不支持hash。
frozenset是不可变集合,存在hash值,因此可以作为字典的key,也可以作为其他集合的元素,缺点是一旦创建就不能更改,没有add、remove方法。
#创建两个集合,一个set,一个frozenset s1 = frozenset('balabala') s2 = set('bala') #作为字典的key d1 = {s1:1,'b':2} print(d1) #可变集合set就会报错 d2 = {s2:1,'b':2} print(d2) TypeError: unhashable type: 'set'
globals() 所有的全局变量
locals() 所有的局部变量
NAME = 'daniel' AGE = 18 JOB = 'IT' def f1(num): if num > 2: print('{}你输入的数字 {} 好大啊'.format(NAME,num)) else: print('{}你输入的数字 {} 不够大啊!'.format(NAME,num)) return num num = input('请输入一个数字试试?').strip() if num.isdigit(): num = int(num) f1(num) print('整个全局变量有 {}'.format(globals())) print('文件中的局部变量有{}'.format(locals())) 输出结果: 请输入一个数字试试?3 daniel你输入的数字 3 好大啊 整个全局变量有 {'JOB': 'IT', '__loader__': <_frozen_importlib_external.SourceFileLoader object at 0x1018a4cc0>, 'num': 3, '__spec__': None, '__name__': '__main__', '__cached__': None, '__file__': '/Users/daniel/PycharmProjects/S13/day4/写博客.py', '__doc__': None, '__package__': None, 'AGE': 18, '__builtins__': <module 'builtins' (built-in)>, 'f1': <function f1 at 0x10186c048>, 'NAME': 'daniel'} 文件中的局部变量有{'JOB': 'IT', '__loader__': <_frozen_importlib_external.SourceFileLoader object at 0x1018a4cc0>, 'num': 3, '__spec__': None, '__name__': '__main__', '__cached__': None, '__file__': '/Users/daniel/PycharmProjects/S13/day4/写博客.py', '__doc__': None, '__package__': None, 'AGE': 18, '__builtins__': <module 'builtins' (built-in)>, 'f1': <function f1 at 0x10186c048>, 'NAME': 'daniel'}
hash() 将元素生成定长hash值
>>> a = 'daniel' >>> b = '1023u0ksjlfjslkjf0093940102kskdkffl0;;;fjjjfnvnflf' >>> hash(a) -1628922583924903800 >>> hash(b) -4360187009688213819
id() 查看对象内存指针
>>> a = 'daniel' >>> b = a >>> a = 'jerry' >>> id(a) 4322605408 >>> id(b) 4322604960 >>> a 'jerry' >>> b 'daniel'
input() 接受用户键盘输入,python3中默认用户输入的是字符串类型
>>> name = input("What's your name?") What's your name?daniel >>> print(type(name)) <class 'str'> >>> print(name) daniel >>> age = input('Age') Age18 >>> print(age) 18 >>> print(type(age)) <class 'str'>
isinstance() 判断对象是否是某个类的实例
>>> isinstance(i1,int) True >>> isinstance(i1,str) False >>> isinstance(name,str) True
len() 查看长度
>>> name 'daniel' >>> len(name) 6 >>> l1 [1, 2, 3, 4, 5] >>> len(l1) 5 >>> t1 (1, 2, 3, 4, 5) >>> len(t1) 5
memoryview() python3新增,查看内存地址的类
>>> name = b'daniel' >>> name b'daniel' >>> id(name) 4322277416 >>> memoryview(name) <memory at 0x1019ee108> >>> type(name) <class 'bytes'>
open() 打开文件操作
>>> f = open('a.txt','w+') >>> f.read() '' f.__class__( f.__init__( f._checkReadable( f.mode f.__del__( f.__iter__( f._checkSeekable( f.name f.__delattr__( f.__le__( f._checkWritable( f.newlines f.__dict__ f.__lt__( f._CHUNK_SIZE f.read( f.__dir__( f.__ne__( f._finalizing f.readable( f.__doc__ f.__new__( f.buffer f.readline( f.__enter__( f.__next__( f.close( f.readlines( f.__eq__( f.__reduce__( f.closed f.seek( f.__exit__( f.__reduce_ex__( f.detach( f.seekable( f.__format__( f.__repr__( f.encoding f.tell( f.__ge__( f.__setattr__( f.errors f.truncate( f.__getattribute__( f.__sizeof__( f.fileno( f.writable( f.__getstate__( f.__str__( f.flush( f.write( f.__gt__( f.__subclasshook__( f.isatty( f.writelines( f.__hash__( f._checkClosed( f.line_buffering
pow() 求幂
>>> i1 18 >>> pow(i1,2) 324 >>> pow(i1,3) 5832
print() 打印各种。。。
>>> print('hello world') hello world >>> print('DBQ 好帅') DBQ 好帅
range() 范围,用的太多了...
>>> for i in range(5): ... print(i) ... 0 1 2 3 4
reversed() 翻转, 和列表、元组等中的翻转一样
>>> l1 [1, 2, 3, 4, 5] >>> t1 (1, 2, 3, 4, 5) >>> reversed(l1) <list_reverseiterator object at 0x101a5ba20> >>> print(reversed(l1)) <list_reverseiterator object at 0x101a5beb8> >>> print(list(reversed(l1))) [5, 4, 3, 2, 1] >>> print(reversed(t1)) <reversed object at 0x101a5bc18> >>> print(tuple(reversed(t1))) (5, 4, 3, 2, 1)
round() 四舍五入
>>> i = 3.1415926 >>> round(i) 3 #可以跟个显示几位 >>> round(i,2) 3.14 >>> round(i,3) 3.142
sorted() 排序, 和列表、元组中的排序一样
>>> l2 = [5,22,4,2,55,23,] >>> sorted(l2) [2, 4, 5, 22, 23, 55]
type() 查看对象类型
>>> type(l1) <class 'list'> >>> type(t1) <class 'tuple'> >>> type(name) <class 'bytes'>
slice() 切片,和字符串、列表中的切片一样
>>> l1 [1, 2, 3, 4, 5] >>> l1[1:5] #这个效果和下面实现的是一样的 [2, 3, 4, 5] >>> l1.__getitem__(slice(1,5,None)) [2, 3, 4, 5] #还可以调整步长 >>> l1.__getitem__(slice(1,5,2)) [2, 4] >>> l1.__getitem__(slice(1,5,1)) [2, 3, 4, 5] >>> l1.__getitem__(slice(0,5,1)) [1, 2, 3, 4, 5] >>> l1.__getitem__(slice(0,5,1))
zip() 河边元素,如把多个列表中的每个元素合并成一个元组:
>>> a = [1,2,3,4,5] >>> b = ['a','b','c','d','e',] >>> zip(a,b) <zip object at 0x101a5ca08> >>> print(tuple(zip(a,b)) ) ((1, 'a'), (2, 'b'), (3, 'c'), (4, 'd'), (5, 'e')) #如果元素长度不一样,会忽略 >>> c = [5,4,3,2] >>> print(tuple(zip(a,c))) ((1, 5), (2, 4), (3, 3), (4, 2))
其他的一些内置函数都是面向对象、模块、迭代器相关的知识,目前还涉及不到,还不懂,也不啰嗦;
classmethod()
complex()
delattr()
getattr()
hasattr()
setattr()
issubclass()
iter()
object()
property()
repr()
staticmethod()
super()
vars()
二. 装饰器
Python中一切皆对象,所以函数当然也是一个对象,而且函数对象被赋值给变量,所以通过变量也能调用该函数;
>>> def f1(): ... print('hello boy') ... >>> a = f1() hello boy >>> a = f1 >>> a() hello boy
假设,我们现在要对f1函数增加功能,比如在给函数调用前打印日志信息,但又不能修改f1的函数,这种在代码运行期间动态增加功能的方式,就是“装饰器"(Decorator). 当然你肯定会说,我直接在f1函数里写个打印日志功能就好了,可如果有5个函数呢?100个函数呢?而且,我们应遵循一种”开放封闭的原则“,也就是说写好的函数,一般不要直接在里面修改。
现在我们定义一个log日志的装饰器:
def log(func): def inner(*args,**kwargs): print('这里输出日志信息,是在执行f1之前执行的') result = func(*args,**kwargs) print('这是输出日之后, 执行完f1之后的信息') return result return inner @log def f1(): print('hello f1') a = f1 a()
输出结果如下:
这里输出日志信息,是在执行f1之前执行的
hello f1
这是输出日之后, 执行完f1之后的信息
也就是说装饰器是在外部装饰函数的,在不改变调用者的基础上,可以在执行函数前后添加功能。语法是: 在调用者前面加 @函数名
总结一下,装饰器的功能:
- 自动执行log函数,并将下面的函数名f1当做参数传递(func)
- 将log函数的返回值,重新赋值给f1
- 一旦函数被装饰器装饰,这个函数就会被重新赋值,赋值成装饰器函数的内存函数。
- func装饰的是原函数f1。
这里有个例子,有个用户验证程序,比如说登陆某宝,要查看购物车的时候,系统肯定提示你要先登录,你点登陆会提示你输入用户名、密码,你检查购物车,会根据你的历史记录打印出购物车的信息等等;
#!/usr/bin/env python3 # -*- coding: utf-8 -*- # Author: DBQ(Du Baoqiang) #先定义一个用户字典,判断用户状态,用户身份等 USER_INFO = {'user_state': False, 'admin_flag':2} #搞一个装饰器,装饰管理后台,检查用户身份等 def outer(func): def inner(*args,**kwargs): if USER_INFO['user_state']: result = func(*args,**kwargs) return result else: print('你没有登陆系统,请登陆后再操作!') return inner #使用装饰器装饰 @outer def manager(): print('欢迎登陆到管理员界面') #检查用户身份函数 @outer def checkuser(username): if USER_INFO['admin_flag'] == 0: print('{} 您的用户是管理员身份'.format(username)) else: print('{} 普通用户啦'.format(username)) #登录函数 def login(username,userpwd): if username == 'tom' and userpwd == '123': USER_INFO['user_state'] = True USER_INFO['current_user'] = username USER_INFO['admin_flag'] = 0 manager() elif username == 'jerry' and userpwd == '123': USER_INFO['user_state'] = True USER_INFO['current_user'] = username USER_INFO['admin_flag'] = 1 else: print('用户名或者密码错误!') #print('欢迎登陆 %s' %username) #主函数 def main(): while True: print('1: 管理后台 2: 登陆 3. 检查用户身份 4. 退出') user_input_num = input('选择下吧:').strip() if user_input_num == '1': result = manager() elif user_input_num == '2': username = input('请输入您的用户名:').strip() userpwd = input('密码').strip() login(username,userpwd) elif user_input_num == '3': checkuser(USER_INFO.get('current_user',None)) elif user_input_num == '4': print('Bye') break if __name__ == '__main__': main()