文章目录
1.函数
语法
def 函数名 ([参数列表]) :
‘’‘文档字符串’‘’
函数体/若干语句
要点
1.我们使用def来定义函数,然后就是一个空格和函数名称;
(1)Python执行def时,会创建一个函数对象,并绑定到函数名变量上。
2.参数列表
(1)圆括号内是形式参数列表,有多个参数则使用逗号隔开
(2)形式参数不需要声明类型,也不需要指定函数返回值类型
(3)无参数,也必须保留空的圆括号
(4)实参列表必须与形参列表一一对应
3.return返回值
(1)如果函数体中包含return语句,则结束函数执行并返回值;
(2)如果函数体中不包含return语句,则返回None值。
4.调用函数之前,必须要先定义函数,即先调用def创建函数对象
(1)内置函数对象会自动创建
(2)标准库和第三方库函数,通过import导入模块时,会执行模块中的def语句
特性
函数的复制
函数也是对象,函数不带圆括号时作为对象处理,这意味着函数也可以浅复制,例如
zhengshu = int
zhengshu("234")
此时zhengshu()等同于int()
作用域
函数内部变量为局部变量,如有必要,须要用global关键字声明以操作全局变量
m=1
def func():
global m
m = 0
return 1
func()
print(m)
#输出0
m=1
def func():
m = 0
return 1
func()
print(m)
#输出1
m=1
def func():
global m
global n
n=m
return 1
func()
print(n)
#输出1
深复制与浅复制
Python的深复制和浅复制有一个很简单的调用方法
import copy
b=copy.copy(a)
b=copy.deepcopy(a)
lambda表达式和匿名函数
lambda表达式可以用来声明匿名函数。lambda函数是一种简单的、在同一行中定义函数的方法。lambda函数实际生成了一个函数对象。
lambda表达式只允许包含一个表达式,不能包含复杂语句,该表达式的计算结果就是函数的返回值。
lambda表达式的基本语法如下:
lambda arg1,arg2,arg3… : <表达式>
arg1/arg2/arg3为函数的参数。<表达式>相当于函数体。运算结果是:表达式的运算结果。
如
f=lambda a,b,c:print(a+b-c)
f(1,2,3)
或
(lambda a,b,c:print(a+b-c))(1,2,3)
eval()函数
功能:将字符串str当成有效的表达式来求值并返回计算结果。
语法: eval(source[, globals[, locals]]) -> value
参数:
source:一个Python表达式或函数compile()返回的代码对象
globals:可选。必须是dictionary
locals:可选。任意映射对象
实例
a = 1
b = 2
print(eval('a+b'))
#输出:3
print(eval('a+b', {'a': 1, 'b': 2}))
#输出:3
nonlocal关键字
nonlocal 用来声明外层的局部变量。
global 用来声明全局变量。
LEGB规则
Python在查找“名称”时,是按照LEGB规则查找的:
Local–>Enclosed–>Global–>Built in
Local 指的就是函数或者类的方法内部
Enclosed 指的是嵌套函数(一个函数包裹另一个函数,闭包)
Global 指的是模块中的全局变量
Built in 指的是Python为自己保留的特殊名称。
如果某个name映射在局部(local)命名空间中没有找到,接下来就会在闭包作用域(enclosed)进行搜索,如果闭包作用域也没有找到,Python就会到全局(global)命名空间中进行查找,最后会在内建(built-in)命名空间搜索 (如果一个名称在所有命名空间中都没有找到,就会产生一个NameError)。
参数
默认值参数
我们可以为某些参数设置默认值,这样这些参数在传递时就是可选的。称为“默认值参数”。默认值参数放到位置参数后面。例如:
def func(r=10):
for temp in range(r):
print(temp, end=' ')
return 22
print(func())
#输出 0 1 2 3 4 5 6 7 8 9 22
位置参数
函数调用时,实参默认按位置顺序传递,需要个数和形参匹配。按位置传递的参数,称为:“位置参数”。实际上就是其他语言的参数。
命名参数
我们也可以按照形参的名称传递参数,称为“命名参数”,也称“关键字参数”。例如:
def func(name,age,job):
print((name,age,job))
func(1,2,3)
func(age=2,job=3,name=1)
输出
(1, 2, 3)
(1, 2, 3)
可变参数
可变参数指的是“可变数量的参数”。分两种情况:
-
*param(一个星号),将多个参数收集到一个“元组”对象中。
-
**param(两个星号),将多个参数收集到一个“字典”对象中。
例如:
def func(a, b, *c):
print(a, b, c)
func(1, 2, 3, 4, 5, 6)
#1 2 (3, 4, 5, 6)
def func(a, b, **c):
print(a, b, c)
func(1, 2, m=1, n=2)
#1 2 {'m': 1, 'n': 2}
强制命名参数
在带星号的“可变参数”后面增加新的参数,必须在调用的时候“强制命名参数”。
2.类对象
定义与实例化
class Person:
def __init__(self, name, age):#构造函数
self.name = name
self.age = age
def getName(self):
return self.name
def getAge(self):
return self.age
p0 = Person("张三", 22)#实例化
new()方法: 用于创建对象,但我们一般无需重定义该方法。
如果我们不定义__init__方法,系统会提供一个默认的__init__方法。如果我们定义了带参的__init__方法,系统不创建默认的__init__方法。
相关函数
dir(obj)#获得对象的所有属性、方法
obj.__dict__ #获取对象的属性字典
pass #空语句
isinstance(对象,类型) #判断“对象”是不是“指定类型”
类方法
类方法是从属于“类对象”的方法。类方法通过装饰器@classmethod来定义,格式如下:
@classmethod
def 类方法名(cls [,形参列表]) :
函数体
要点如下:
1.类方法对类属性的操作会导致类的属性彻底改变,之后实例化的对象携带的也都是修改后的属性值
2.第一个cls必须有;cls指的就是“类对象”本身;self则指的是实例化对象
3.调用类方法格式:“类名.类方法名(参数列表)”。 参数列表中,不需要也不能给cls传值。
4.类方法中访问实例属性和实例方法会导致错误
5.子类继承父类方法时,传入cls是子类对象,而非父类对象
静态方法
Python中允许定义与“类对象”无关的方法,称为“静态方法”。
“静态方法”和在模块中定义普通函数没有区别,只不过“静态方法”放到了“类的名字空间里面”,需要通过“类调用”。
静态方法通过装饰器@staticmethod来定义,格式如下:
@staticmethod
def 静态方法名([形参列表]) :
函数体
要点如下:
1.@staticmethod必须位于方法上面一行
2.调用静态方法格式:“类名.静态方法名(参数列表)”。
3.静态方法中访问实例属性和实例方法会导致错误
__call__方法和可调用对象
定义了__call__方法的对象,称为“可调用对象”,即该对象可以像函数一样被调用。
class cal:
def __init__(self):
pass
def __call__(self, a, b):
return a + b
c = cal()
print(c(1, 2))
#输出为3
@property装饰器
该方法用于支持把方法以属性的方式调用,可以方便的把属性封装
注意:此时属性的get和set方法必须同名,否则报错!
'''简单的员工工资修改限制,如果是涨薪,则修改生效;如果是降薪,则修改不生效'''
class employee:
__company = 'cpt'
def __init__(self, name, sal):
self.name = name
self.__salary = sal
@property
def salary(self):
return self.__salary
@salary.setter
def salary(self, newSal):
if newSal > self.__salary:
self.__salary = newSal
print("新工资:" + str(self.__salary))
e = employee('张三', 10000)
print(dir(e))
print(e.salary)
e.salary=9
print(e.salary)
e.salary=900000
print(e.salary)
重载
截止到2023.01.17,Python版本3.10,不支持方法的重载
添加/修改方法
修改方法
class cal:
def __init__(self):
pass
def 加法(self, a, b):
return a + b
c=cal()
print(c.加法(1,2))
def 乘法(self,a,b):
return a*b
cal.加法=乘法
print(c.加法(3,4))
输出为
3
12
添加方法:
class cal:
def __init__(self):
pass
def 加法(self, a, b):
return a + b
c=cal()
print(c.加法(1,2))
def 乘法(self,a,b):
return a*b
cal.乘法=乘法
print(c.加法(3,4))
print(c.乘法(3,4))
输出为
3
7
12
私有属性和私有方法(实现非严格封装)
Python对于类的成员没有严格的访问控制限制,这与其他面向对象语言有区别。关于私有属性和私有方法,有如下要点:
-
通常我们约定,两个下划线开头的属性是私有的(private)。其他为公共的(public)。
-
类内部可以访问私有属性(方法)
-
类外部不能直接访问私有属性(方法)
-
类外部可以通过“对象命._类名__私有属性(方法)名”访问私有属性(方法)
继承
语法
class 子类类名(父类1[,父类2,...]):
类体
*子类并不会自动调用父类的__init__(),我们必须显式的调用它。
*子类自动继承成员,如有需要可直接覆写
*子类调用父类方法,可使用super关键字
mro()方法与__MRO__属性(查看类继承层次)
实例:
class Person:
race = "animal"
def __init__(self, name, age):
self.name = name
self.age = age
class Student(Person):
race = "Person"
print(Student.mro())
print(Student.__mro__)
单例模式
实例:
class Tool:
instance = None
def __init__(self):
self.name = "Tool"
self.age = 0
def test(self):
print("-------------------------test---------------------")
def __new__(cls, *args, **kwargs):
if cls.instance == None:
cls.instance=super(Tool, cls).__new__(cls)
return cls.instance
t = Tool()
t1 = Tool()
t2 = Tool()
print(id(t))
print(id(t1))
print(id(t2))
print(t,t1,t2)
t.test()
t1.test()
t2.test()