目录:
- 函数示例
- 装饰器
- 模块
- 内置函数
一、函数示例:
1、为什么使用函数之模块化程序设计:
不使用模块程序设计的缺点:
1、体系结构不清晰,可主读性差;
2、可扩展性差;
3、程序冗长;
2、定义函数:
def fun(args):
'描述信息'
函数体
return 返回值
定义函数的三种形式:
无参函数
def foo(): print('in the foo') foo()
有参函数:
def bar(x,y): print('in the bar') bar(1,2)
空函数:
def func(): pass
空函数的应用示例:
def put(): pass def get(): pass def cd(): pass def ls(): pass def auth(): pass
3、调用函数:
三种形式:
语句形式:
def foo(): print('in the foo') foo()
表达式形式:
def my_max(x,y) if x>y: return x else: return y res = my_max(1,2) res = 10 * my_max(1,2)
作为另外一个函数的参数:
my_max(1,my_max(2,3)): #先比较2与3的最大值,再与1作比较;
4、函数的返回值三种形式:
不返回函数:
def foo(): print('in the foo') res = foo() print(res)
返回一个函数:
def foo(): return 1 res = foo() print(res)
返回多个:
def foo(): return 1,'s',[1,2,3] res = foo() print(res)
5、函数的参数:
def func(x,y): #形参在调用时才真正占用内存空间,调用结束则释放内存空间; print(x) print(y) fund(1,2) #实参真实占用内存空间; def func(x,y): if type(x) is int and type(y) is int: return x+y func(1,'a') def func(x,y): #使用文档注释来提醒用户输入参数类型; ''' ''' return x+y func(1,'a') def func(x:int,y:int)->int: #只是一个提示作用; pass print(func.__annotations__) 从实参的角度, 按位置传值: def foo(x,y): print(x,y) foo(1,2) 按关键字传参:key = value def foo(x,y): print(x,y) foo(y=2,x=1) #优点:不用按位置来输入参数; 针对同一个形参,要么按照位置要么按照关键字为形参传值;关键字参数必须写到位置参数的右边; 如:foo(1,x=1,y=2) 此方法会报错; 从形参的角度:位置参数,默认参数,可变长参数*args;**kwargs; 按位置定义的形参: def foo(x,y,z): #位置参数;也就是必传值参数; print(x) print(y) print(z) foo(1,2,3) foo(y=2,x=1,z=3) 按默认参数的形参: def foo(x,y=1): #y就是默认参数;但也可以去赋值;默认参数建议不要使用列表或字典等可变类型;必须放在默认参数之后; print(x) print(y) foo(1) 按可变长参数的形参: def foo(x,y=1,*args): #可变长参数必须放在位置参数与默认参数的后面;此情况一般不使用位置参数; print(x) print(y) print(args) foo(1,2,3,4,54,6,3,y=2) #错 foo(1,2,3,4,54,y=2,3,5) #错 foo(1,2,3,4,54,6,3) #对 def foo(x,y,*args): print(x) print(y) print(*args) l=['a','b'] foo(1,2,*1) #*args的形式就等于1,2,3,4,5 解包; ('a','b') def foo(x,y,z): print(x) print(y) print(z) # foo(1,2,3) l=[1,2,3] foo(*l) def foo(x,**kwargs): print(x) print(kwargs) foo(1,y=3,z=2) dic = {'a':1,'b':2} foo(1,**dic) #foo(1,a=1,b=2) def foo(x,y,z): print(x,y,z) foo(**{'a':1,'b':2,'c':3}) #foo(a=1,b=2,c=3),要把a,b,c改成x,y,z foo(**{'x':1,'y':2,'z':3}) 注:位置参数 -> 默认参数,*args, **kwargs 1、*args 相当于展开按照位置的方式去写; 2、**kwargs 相当于把kwargs按照关键字的方式去写;
6、函数是第一类对象的意思就是函数可以被当作数据来传递;
def func() print('in the fun') fl = fun fl() 函数可作为参数:高阶函数: def foo(x): x() foo(func) 返回值可以是函数: ########################################## 可以作为容器类型的元素: func_dic={ 'func':func } func_diuc['func']()
7、函数的嵌套:分为两种:
嵌套的调用: def my_max1(a,b,c,d): res1=my_max(a,b) res2=my_max(res1,c) res3=my_max(res2,d) return res3 def my_max(x,y): if x > y: return x else: return y print(my_max1(100,2,-1,5)) 嵌套的定义: python支持静态的嵌套域; x=1 def f1(): def f2(): print(x) #def f3(): # print(x) #return f3 return f2 f2=f1() 闭包函数: def f1(): x=1 def f2(): print(x) return f2 f = f1() f() 示例: from urllib request import urlopen #用来爬网页; def page(url): def get(): return urlopen(url).read() return get baidu = page('http//ww.baidu.com') python = page('http://www.python.org') baidu()
二、装饰器
装饰器:在遵循下面的两个原则 的前提下为被修饰者添加新功能;
函数功能的扩展原则:
1、一定不能修改源代码;
2、不能改变函数的调用方式;
装饰器本身是一个函数,被装饰的也是一个函数;
示例:
def index(): print('in the ndex') index() @timer #表示方法:index = timer(index) def index(): print('in the ndex') index() 装饰器的叠加: @deco3 @deco2 @deco1 #func1 = deco1(index) --> func2=deco2(func1) --> index= deco3(func2)====>index=deco3(deco2(deco1(index))) def index(): print('in the ndex') index() 示例: from urllib request import urlopen #用来爬网页; import time def timer(func): def wrapper(): print('in the wrapper-->start') start_time=time.time() func() print('in the wrapper-->stop') return wrapper @timer #表示方法:index = timer(index) def index(): print('in the ndex') index() from urllib request import urlopen #用来爬网页; import time def timer(func): def wrapper(*args,**kwargs): #一定不要写死; print('in the wrapper-->start') start_time=time.time() res=func(*args,**kwargs) #home('tom',msg='xxxx')-->home(user,msg) *与位置等同 func(msg) #运行最原始的index -> index(msg) print('in the wrapper-->stop') return res return wrapper @timer #表示方法:index = timer(index) def index(msg): print('in the ndex',msg) @timer def home(user,msg): print('in the home %s %s',%(user,msg) return 1 #返回值要写在wrapper中 index('hello world') home('tom',msg='xxxx')
三、模块
什么是模块:
模块就是一个包含了python定义和声明的文件;文件名就是模块名字加上.py的后缀;
模块只会被导入一次,第一次会导入到内存中,第二次再导入直接去内存调用
模块的导入:
第一次导入模块三个事件:
1、创建新的作用域;
2、在该作用域内执行顶级代码;
3、得到一个模块名,绑定到该模块内的代码;
为模块起别名: import spam as sm print(sm.money) from spam import read1 as rea 导入多个模块: import ms,spam,re from spam import (read1,change)可写入多行; 导入模块的另外一种形式: from .. import .. from spam import read1 read1()
总结:
从那来就从哪执行,与调用的位置无关;
将module中所有非下划线开头的名称导入: from module import * __all__ = ['money','read1']
注:
模块不支持重载;要加载需要重启程序;
把文件当做和脚本执行__name__等于'__main__'; print(__name__) 把spam.py文件当作模块去使用__name__等于'spam' if __name__ = '__main__': print('文件被当作脚本执行时触发的代码') 可以控制python代码在不同场景下运行的代码;
模块路径的查找:
import sys
sys.path
路径的查找先找内置的路径,再找其他的路径;
来源:
1、当前目录;
2、python path
3、安装时依赖的一些目录;
sys.path.append(r'/test') #当前目录有效;
r表示对特殊字符的转义;
sys.path.insert(0,r'/test') #从0的位置插入;
导入模块时,先从内建中找相同的模块名,找不到就去sys.path中找;
dir()
不会列举出内建模块的名字;
import builtins
dir(builtins)
包:
包是一种通过使用‘.模块名’来组织python模块名称空间的方式。
无论是import形式还是from...import形式,凡是在导入语句中(而不是在使用时)遇到带点的,都要第一时间提高警觉:这是关于包才有的导入语法
包的本质就是一个包含__init__.py文件的目录。
from ... import ...
需要注意的是from后import导入的模块,必须是明确的一个不能带点,否则会有语法错误,如:from a import b.c是错误语法
__init__.py文件
不管是哪种方式,只要是第一次导入包或者是包的任何其他部分,都会依次执行包下的__init__.py文件(我们可以在每个包的文件内都打印一行内容来验证一下),这个文件可以为空,但是也可以存放一些初始化包的代码。
from glance.api import *
在讲模块时,我们已经讨论过了从一个模块内导入所有*,此处我们研究从一个包导入所有*。
此处是想从包api中导入所有,实际上该语句只会导入包api下__init__.py文件中定义的名字,我们可以在这个文件中定义__all___: #在__init__.py中定义 x=10 def func(): print('from api.__init.py') __all__=['x','func','policy']
此时我们在于glance同级的文件中执行from glance.api import *就导入__all__中的内容(versions仍然不能导入)。
示例:
from glance.api import * 只会运行api下的__init__.py文件; 在api\__init__.py中输入: __all__ = ['policy','versions'] import只能导入内建与第三方的模块,否则会出错;
四、内置函数
内置函数解释: # !/usr/bin/env python # -*- coding:utf-8 -*- #返回数字的绝对值。 参数可以是整数或浮点数。 如果参数是复数,则返回其大小。 print(abs(-1.11)) #传入一个可被循环的元素,如果这个元素中有一个为False则都为假 # 0 空值 False 都为假 print(all([1,2,3])) #与all相反,只有一个为真,则为真; print(any([0,2,False])) #这个函数跟repr()函数一样,返回一个可打印的对象字符串方式表示。当遇到非ASCII码时 #就会输出x,u或U等字符来表示。与Python 2版本里的repr()是等效的函数。 print(ascii("dsads"),ascii(66),ascii('b23')) #将十进制转换为二进制; print(bin(10)) #返回布尔值,即True或False之一,如果参数为false或省略,则返回False; 否则返回True。 print(bool(1)) #根据传入的参数创建一个新的字节数组 #如果传入字符串必须给出编码 print(bytearray('你好','utf-8')) #当source参数是一个可迭代对象,那么这个对象中的元素必须符合大于0 小于256 print(bytearray([256,1,2])) #返回一个的“bytes”对象,返回bytes类型 bytes('中文','utf-8') #检查对象是否可以被调用 def func(): pass print(callable(func)) #返回整数所对应的Unicode字符,chr(97)返回字符串'a',而chr(8364)返回字符串'€'。 print(chr(126)) #是用来指定一个类的方法为类方法,类方法可以不实例化直接调用 class A: @classmethod def B(cls,arg1,): print(arg1) A.B(1) A().B(1) #将源编译为代码或者AST对象。代码对象能够通过exec语句来执行或者eval()进行求值。 #源可以是正常字符串,字节字符串或AST对象。 expr = "5+5-1" obj = compile(expr,"","eval") print(eval(obj)) #返回值为real + imag * j的复数或者转化一个字符串或数为复数。如果第一个参数为字符串,则不需要指定第二个参数。 print(complex(1, 2)) print(complex(1)) print(complex("1+2j")) # 参数是一个对象和一个字符串。 该字符串必须是对象属性之一的名称。 class A: def a1(self): print("a1") def a2(self): print("a2") obj = A print(dir(obj)) delattr(obj, "a1") print(dir(obj)) #dir 返回对象中的方法 strs="aaa" print(dir(strs)) #返回两个数值的商和余数 print(divmod(7,3)) #用于遍历序列中的元素以及它们的下标 print(enumerate([1,2,3]))#返回的是可迭代的对象 for i,j in enumerate(('A','B','C')): print(i,j) #将字符串str当成有效的表达式来求值并返回计算结果。 print(eval("1+2+3")) print(eval("False or True")) #字符串str当成动态语句块执行并返回结果 exec('a=1+2+3') print(a) #使用指定方法(方法,函数),过滤可迭代对象的元素 def add(arg): return arg > 3 for i in filter(add,[1,2,3,4,5]): print(i) #浮点型 print(float(11)) #格式化显示 更多方法请参考官方说明 print('{:,.2f}'.format(111111)) #根据传入的参数创建一个新的不可变集合 a = frozenset([1,2,3,4,5]) print(a) #获取对象的属性值 class A(): def __init__(self,): self.name = "123" b = A() print(getattr(b,'name')) #返回当前作用域内的全局变量和其值组成的字典 print(globals()) #检查对象是否含有属性 class A(): def __init__(self,): self.name = "123" b = A() print(hasattr(b,'name')) #哈希值计算 #在当前环境中是唯一的 print(hash('Hello')) #help帮助 def funcs(args): """ Function description :param args: args = list :return: """ pass print(help(funcs)) #转换16进制 print(hex(44)) #显示对象的标识符 print(id("123")) #input标准输入 s = input("user name:") print(s) #int返回整数 print(int(1.2)) print(int("2")) #判断对象是否是类或者类型元组中任意类元素的实例 print(isinstance("1",int)) print(isinstance(1.1,(int,float))) #判断类是否是另外一个类或者类型元组中任意类元素的子类 print(dir(str)) print(issubclass(bytearray,str)) print(issubclass(bool,int)) #根据传入的参数创建一个新的可迭代对象 a = iter('12345') print(next(a)) print(next(a)) #返回对象的长度len a = [1,2,3,4] #转换列表 print(list("abcd")) #返回当前作用域内的局部变量和其值组成的字典 def A(): print(locals()) s = 1 print(locals()) A() #使用指定方法去作用传入的每个可迭代对象的元素,生成新的可迭代对象 def add(x): return x+100 lists = [1,2,3,4] for i in map(add,lists): print(i) #max:返回最大值 print(max(1,2,3)) print(max([1,2,3,4])) #在进行切片并赋值数据时,不需要重新copy原列表数据,可以直接映射原数据内存; s = memoryview(b'abcd') print(s[1]) #返回最小值 print(min(1,2,3)) print(min([2,3])) #返回可迭代对象中的下一个元素值 a = iter('1234') print(next(a)) #创建一个新的object对象(新式类) class B(object): pass #转化成8进制数字符串 print(oct(10)) #open文件操作 file = open('test.txt',encoding="utf-8") #ord:返回Unicode字符对应的整数 print(ord("A")) #幂运算 print(pow(2,3)) #标准输出 print() #property:标示属性的装饰器 #类中使用具体方法请百度,或者等待后续更新 property #range:根据传入的参数创建一个新的range对象 range(10) range(1,10) """repr()函数得到的字符串通常可以用来重新获得该对象,repr()的输入对python比较友好。 通常情况下obj==eval(repr(obj))这个等式是成立的。""" obj='Python' print(eval(repr(obj))) #翻转序列 a = reversed([1,2,3,4,5]) print(list(a)) #round:对浮点数进行四舍五入求值 print(round(1.5)) #set 转换成集合 print(set([1,2,3])) #setattr:设置对象的属性值 class A(): def __init__(self,age): self.age = age s = A(11) print(s.age) setattr(s,'age',22) print(s.age) #根据传入的参数创建一个新的切片对象 c1 = slice(3) c2 = slice(2,4) c3 = slice(0,5,2) s = [1,2,3,4,5,6] print(s[c1]) print(s[c2]) print(s[c3]) #排序,返回一个新的列表默认按字符ascii码排序 a = [4,3,2,1,7] print(sorted(a)) #标示方法为静态方法的装饰器 class B(object): def __init__(self,age): self.age = age @staticmethod def hello(args): print(args) B.hello("Hello World") #字符串类型 print(str(123)) #求和 print(sum([1,2,3,4])) #根据传入的参数创建一个新的子类和父类关系的代理对象 class A(object): def __init__(self): print("我是 A Clase") class B(A): def __init__(self): print("我是 B Class") super().__init__() b = B() #元祖 tuple([1,2,3,4]) #type 返回对象的类型 print(type([1])) print(type("1")) #返回当前作用域内的局部变量和其值组成的字典,或者返回对象的属性列表 def func(): print(vars()) s = 1 print(vars()) func() #聚合传入的每个迭代器中相同位置的元素,返回一个新的元组类型迭代器 list1 = [1,2,3] list2 = ["A","B","C","D"] print(zip(list1,list2)) for i in zip(list1,list2): print(i) #__import__:动态导入模块 __import__