1. 变量
变量名自定义,要满足标识符命名规则。
标识符命名规则是Python中定义各种名字的时候的统一规范,具体如下:
- 由数字、字母、下划线组成
- 不能数字开头
- 不能使用内置关键字
- 严格区分大小写
False None True and as assert break class
continue def del elif else except finally for
from global if import in is lambda nonlocal
not or pass raise return try while with
yield
2. 命名习惯
- 见名知义。
- 大驼峰:即每个单词首字母都大写,例如:
MyName 。 - 小驼峰:第二个(含)以后的单词首字母大写,例如:
myName 。 - 下划线:例如:
my_name 。
3. 格式化输出
所谓的格式化输出即按照一定的格式输出内容。
3.1 格式化符号
格式符号 | 转换 |
---|
%s | 字符串 | %d | 有符号的十进制整数 | %f | 浮点数 | %c | 字符 | %u | 无符号十进制整数 | %o | 八进制整数 | %x | 十六进制整数(小写ox) | %X | 十六进制整数(大写OX) | %e | 科学计数法(小写’e’) | %E | 科学计数法(大写’E’) | %g | %f和%e的简写 | %G | %f和%E的简写 |
技巧
- %06d,表示输出的整数显示位数,不足以0补全,超出当前位数则原样输出
- %.2f,表示小数点后显示的小数位数。
3.2 体验
格式化字符串除了%s,还可以写为f'{表达式}'
age = 18
name = 'TOM'
weight = 75.5
student_id = 1
print('我的名字是%s' % name)
print('我的学号是%4d' % student_id)
print('我的体重是%.2f公斤' % weight)
print('我的名字是%s,今年%d岁了' % (name, age))
print('我的名字是%s,明年%d岁了' % (name, age + 1))
print(f'我的名字是{name}, 明年{age + 1}岁了')
f-格式化字符串是Python3.6中新增的格式化方法,该方法更简单易读。
3.3 转义字符
\n :换行。\t :制表符,一个tab键(4个空格)的距离。
3.4 结束符
想一想,为什么两个print会换行输出?
print('输出的内容', end="\n")
在Python中,print(), 默认自带end="\n" 这个换行结束符,所以导致每两个print 直接会换行展示,用户可以按需求更改结束符。
4. 转换数据类型
转换数据类型的函数
函数 | 说明 |
---|
int(x [,base ]) | 将x转换为一个整数 | float(x ) | 将x转换为一个浮点数 | complex(real [,imag ]) | 创建一个复数,real为实部,imag为虚部 | str(x ) | 将对象 x 转换为字符串 | repr(x ) | 将对象 x 转换为表达式字符串 | eval(str ) | 用来计算在字符串中的有效Python表达式,并返回一个对象 | tuple(s ) | 将序列 s 转换为一个元组 | list(s ) | 将序列 s 转换为一个列表 | chr(x ) | 将一个整数转换为一个Unicode字符 | ord(x ) | 将一个字符转换为它的ASCII整数值 | hex(x ) | 将一个整数转换为一个十六进制字符串 | oct(x ) | 将一个整数转换为一个八进制字符串 | bin(x ) | 将一个整数转换为一个二进制字符串 |
5. 数据类型
5.1 字符串
- find():检测某个子串是否包含在这个字符串中,如果在返回这个子串开始的位置下标,否则则返回-1。
- 语法
字符串序列.find(子串, 开始位置下标, 结束位置下标)
注意:开始和结束位置下标可以省略,表示在整个字符串序列中查找。
- index():检测某个子串是否包含在这个字符串中,如果在返回这个子串开始的位置下标,否则则报异常。
- 语法
字符串序列.index(子串, 开始位置下标, 结束位置下标)
注意:开始和结束位置下标可以省略,表示在整个字符串序列中查找。
-
rfind(): 和find()功能相同,但查找方向为右侧开始。 -
rindex():和index()功能相同,但查找方向为右侧开始。 -
count():返回某个子串在字符串中出现的次数 -
replace():替换 -
split():按照指定字符分割字符串。 -
join():用一个字符或子串合并字符串,即是将多个字符串合并为一个新的字符串。 -
capitalize():将字符串第一个字符转换成大写。
注意:capitalize()函数转换后,只字符串第一个字符大写,其他的字符全都小写。
- title():将字符串每个单词首字母转换成大写。
- lower():将字符串中大写转小写。
- upper():将字符串中小写转大写。
- lstrip():删除字符串左侧空白字符。
- ljust():返回一个原字符串左对齐,并使用指定字符(默认空格)填充至对应长度 的新字符串。
- rjust():返回一个原字符串右对齐,并使用指定字符(默认空格)填充至对应长度 的新字符串,语法和ljust()相同。
- center():返回一个原字符串居中对齐,并使用指定字符(默认空格)填充至对应长度 的新字符串,语法和ljust()相同。
- endswith()::检查字符串是否是以指定子串结尾,是则返回 True,否则返回 False。如果设置开始和结束位置下标,则在指定范围内检查。
- isalpha():如果字符串至少有一个字符并且所有字符都是字母则返回 True, 否则返回 False。
- isdigit():如果字符串只包含数字则返回 True 否则返回 False。
- isalnum():如果字符串至少有一个字符并且所有字符都是字母或数字则返 回 True,否则返回 False。
- isspace():如果字符串中只包含空白,则返回 True,否则返回 False。
5.2 列表
- index():返回指定数据所在位置的下标 。
- count():统计指定数据在当前列表中出现的次数。
- in:判断指定数据在某个列表序列,如果在返回True,否则返回False
- append():列表结尾追加数据。
如果append()追加的数据是一个序列,则追加整个序列到列表 - extend():列表结尾追加数据,如果数据是一个序列,则将这个序列的数据逐一添加到列表。
- insert():指定位置新增数据。
- del/del name_list[0]
- pop():删除指定下标的数据(默认为最后一个),并返回该数据。
- remove():移除列表中某个数据的第一个匹配项。
- clear():清空列表
- reverse()
- sort()
- copy()
5.3 元组
- 按下标查找数据
- index():查找某个数据,如果数据存在返回 对应的下标,否则报错,语法和列表、字符串的index方法相同。
- count():统计某个数据在当前元组出现的次数。
- len():统计元组中数据的个数。
5.4 字典
- 增:字典序列[key] = 值
- del() / del:删除字典或删除字典中指定键值对。
- clear():清空字典
- key值查找
- 字典序列.get(key, 默认值)
- keys()
- values()
- items()
5.5 集合
- 创建集合使用
{} 或set() , 但是如果要创建空集合只能使用set() ,因为{} 用来创建空字典。 - add()
- update(), 追加的数据是序列。
- remove(),删除集合中的指定数据,如果数据不存在则报错。
- discard(),删除集合中的指定数据,如果数据不存在也不会报错。
- pop(),随机删除集合中的某个数据,并返回这个数据。
- in:判断数据在集合序列
6. 公共操作
6.1 公共方法
函数 | 描述 |
---|
len() | 计算容器中元素个数 | del 或 del() | 删除 | max() | 返回容器中元素最大值 | min() | 返回容器中元素最小值 | range(start, end, step) | 生成从start到end的数字,步长为 step,供for循环使用 | enumerate() | 函数用于将一个可遍历的数据对象(如列表、元组或字符串)组合为一个索引序列,同时列出数据和数据下标,一般用在 for 循环当中。 |
7. 推导式
7.1 列表推导式
作用:用一个表达式创建一个有规律的列表或控制一个有规律列表。
列表推导式又叫列表生成式。
1.1 快速体验
需求:创建一个0-10的列表。
list1 = []
i = 0
while i < 10:
list1.append(i)
i += 1
print(list1)
list1 = []
for i in range(10):
list1.append(i)
print(list1)
list1 = [i for i in range(10)]
print(list1)
1.2 带if的列表推导式
需求:创建0-10的偶数列表
list1 = [i for i in range(0, 10, 2)]
print(list1)
list1 = [i for i in range(10) if i % 2 == 0]
print(list1)
1.3 多个for循环实现列表推导式
需求:创建列表如下:
[(1, 0), (1, 1), (1, 2), (2, 0), (2, 1), (2, 2)]
list1 = [(i, j) for i in range(1, 3) for j in range(3)]
print(list1)
7.2 字典推导式
思考:如果有如下两个列表:
list1 = ['name', 'age', 'gender']
list2 = ['Tom', 20, 'man']
如何快速合并为一个字典?
答:字典推导式
字典推导式作用:快速合并列表为字典或提取字典中目标数据。
2.1 快速体验
- 创建一个字典:字典key是1-5数字,value是这个数字的2次方。
dict1 = {i: i**2 for i in range(1, 5)}
print(dict1)
- 将两个列表合并为一个字典
list1 = ['name', 'age', 'gender']
list2 = ['Tom', 20, 'man']
dict1 = {list1[i]: list2[i] for i in range(len(list1))}
print(dict1)
- 提取字典中目标数据
counts = {'MBP': 268, 'HP': 125, 'DELL': 201, 'Lenovo': 199, 'acer': 99}
count1 = {key: value for key, value in counts.items() if value >= 200}
print(count1)
7.3 集合推导式
需求:创建一个集合,数据为下方列表的2次方。
list1 = [1, 1, 2]
代码如下:
list1 = [1, 1, 2]
set1 = {i ** 2 for i in list1}
print(set1)
注意:集合有数据去重功能。
7.4 总结
[xx for xx in range()]
{xx1: xx2 for ... in ...}
{xx for xx in ...}
8. 函数
8.1 变量作用域
变量作用域指的是变量生效的范围,主要分为两类:局部变量和全局变量。
所谓局部变量是定义在函数体内部的变量,即只在函数体内部生效。
局部变量的作用:在函数体内部,临时保存数据,即当函数调用完成后,则销毁局部变量。
所谓全局变量,指的是在函数体内、外都能生效的变量。
8.2 多函数程序执行流程
一般在实际开发过程中,一个程序往往由多个函数(后面知识中会讲解类)组成,并且多个函数共享某些数据,如下所示:
glo_num = 0
def test1():
global glo_num
glo_num = 100
8.3 函数的参数
- 位置参数:调用函数时根据函数定义的参数位置来传递参数。
注意:传递和定义参数的顺序及个数必须一致。
- 函数调用,通过“键=值”形式加以指定。可以让函数更加清晰、容易使用,同时也清除了参数的顺序需求。
注意:函数调用时,如果有位置参数时,位置参数必须在关键字参数的前面,但关键字参数之间不存在先后顺序。
- 缺省参数也叫默认参数,用于定义函数,为参数提供默认值,调用函数时可不传该默认参数的值(注意:所有位置参数必须出现在默认参数前,包括函数定义和调用)。
注意:函数调用时,如果为缺省参数传值则修改默认参数值;否则使用这个默认值。
def user_info(*args):
print(args)
user_info('TOM')
user_info('TOM', 18)
注意:传进的所有参数都会被args变量收集,它会根据传进参数的位置合并为一个元组(tuple),args是元组类型,这就是包裹位置传递。
def user_info(**kwargs):
print(kwargs)
user_info(name='TOM', age=18, id=110)
综上:无论是包裹位置传递还是包裹关键字传递,都是一个组包的过程。
8.4 拆包和交换变量值
def return_num():
return 100, 200
num1, num2 = return_num()
print(num1)
print(num2)
dict1 = {'name': 'TOM', 'age': 18}
a, b = dict1
print(a)
print(b)
print(dict1[a])
print(dict1[b])
8.5 引用
在python中,值是靠引用来传递来的。
我们可以用id() 来判断两个变量是否为同一个值的引用。 我们可以将id值理解为那块内存的地址标识。
a = 1
b = a
print(b)
print(id(a))
print(id(b))
a = 2
print(b)
print(id(a))
print(id(b))
aa = [10, 20]
bb = aa
print(id(aa))
print(id(bb))
aa.append(30)
print(bb)
print(id(aa))
print(id(bb))
引用当做实参
代码如下:
def test1(a):
print(a)
print(id(a))
a += a
print(a)
print(id(a))
b = 100
test1(b)
c = [11, 22]
test1(c)
效果图如下:
基本数据类型传入的是值,引用数据类型传入的实参引用地址
8.6 可变和不可变类型
所谓可变类型与不可变类型是指:数据能够直接进行修改,如果能直接修改那么就是可变,否则是不可变.
8.7 高阶函数
把函数作为参数传入,这样的函数称为高阶函数,高阶函数是函数式编程的体现。函数式编程就是指这种高度抽象的编程范式。
体验高阶函数
在Python中,abs() 函数可以完成对数字求绝对值计算。
abs(-10)
round() 函数可以完成对数字的四舍五入计算。
round(1.2)
round(1.9)
需求:任意两个数字,按照指定要求整理数字后再进行求和计算。
def add_num(a, b):
return abs(a) + abs(b)
result = add_num(-1, 2)
print(result)
def sum_num(a, b, f):
return f(a) + f(b)
result = sum_num(-1, 2, abs)
print(result)
注意:两种方法对比之后,发现,方法2的代码会更加简洁,函数灵活性更高。
函数式编程大量使用函数,减少了代码的重复,因此程序比较短,开发速度较快。
内置高阶函数
map()
map(func, lst),将传入的函数变量func作用到lst变量的每个元素中,并将结果组成新的列表(Python2)/迭代器(Python3)返回。
需求:计算list1 序列中各个数字的2次方。
list1 = [1, 2, 3, 4, 5]
def func(x):
return x ** 2
result = map(func, list1)
print(result)
print(list(result))
reduce()
reduce(func,lst),其中func必须有两个参数。每次func计算的结果继续和序列的下一个元素做累积计算。
注意:reduce()传入的参数func必须接收2个参数。
需求:计算list1 序列中各个数字的累加和。
import functools
list1 = [1, 2, 3, 4, 5]
def func(a, b):
return a + b
result = functools.reduce(func, list1)
print(result)
filter()
filter(func, lst)函数用于过滤序列, 过滤掉不符合条件的元素, 返回一个 filter 对象。如果要转换为列表, 可以使用 list() 来转换。
list1 = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
def func(x):
return x % 2 == 0
result = filter(func, list1)
print(result)
print(list(result))
8.8 总结
-
递归
-
lambda
lambda 参数列表: 表达式
-
lambda的参数形式
lambda: 表达式
lambda 参数: 表达式
lambda key=value: 表达式
lambda *args: 表达式
lambda **kwargs: 表达式
-
高阶函数
9. 文件操作
9.1 打开文件模式
在python,使用open函数,可以打开一个已经存在的文件,或者创建一个新文件,语法如下:
open(name, mode)
name:是要打开的目标文件名的字符串(可以包含文件所在的具体路径)。
mode:设置打开文件的模式(访问模式):只读、写入、追加等。
打开文件模式
模式 | 描述 |
---|
r | 以只读方式打开文件。文件的指针将会放在文件的开头。这是默认模式。 | rb | 以二进制格式打开一个文件用于只读。文件指针将会放在文件的开头。这是默认模式。 | r+ | 打开一个文件用于读写。文件指针将会放在文件的开头。 | rb+ | 以二进制格式打开一个文件用于读写。文件指针将会放在文件的开头。 | w | 打开一个文件只用于写入。如果该文件已存在则打开文件,并从开头开始编辑,即原有内容会被删除。如果该文件不存在,创建新文件。 | wb | 以二进制格式打开一个文件只用于写入。如果该文件已存在则打开文件,并从开头开始编辑,即原有内容会被删除。如果该文件不存在,创建新文件。 | w+ | 打开一个文件用于读写。如果该文件已存在则打开文件,并从开头开始编辑,即原有内容会被删除。如果该文件不存在,创建新文件。 | wb+ | 以二进制格式打开一个文件用于读写。如果该文件已存在则打开文件,并从开头开始编辑,即原有内容会被删除。如果该文件不存在,创建新文件。 | a | 打开一个文件用于追加。如果该文件已存在,文件指针将会放在文件的结尾。也就是说,新的内容将会被写入到已有内容之后。如果该文件不存在,创建新文件进行写入。 | ab | 以二进制格式打开一个文件用于追加。如果该文件已存在,文件指针将会放在文件的结尾。也就是说,新的内容将会被写入到已有内容之后。如果该文件不存在,创建新文件进行写入。 | a+ | 打开一个文件用于读写。如果该文件已存在,文件指针将会放在文件的结尾。文件打开时会是追加模式。如果该文件不存在,创建新文件用于读写。 | ab+ | 以二进制格式打开一个文件用于追加。如果该文件已存在,文件指针将会放在文件的结尾。如果该文件不存在,创建新文件用于读写。 |
num表示要从文件中读取的数据的长度(单位是字节),如果没有传入num,那么就表示读取文件中所有的数据。
readlines可以按照行的方式把整个文件中的内容进行一次性读取,并且返回的是一个列表,其中每一行的数据为一个元素。
- readline()一次读取一行内容。
- seek()作用:用来移动文件指针。
文件对象.seek(偏移量, 起始位置)
> 起始位置:
>
> - 0:文件开头
> - 1:当前位置
> - 2:文件结尾
9.2 文件和文件夹的操作
在Python中文件和文件夹的操作要借助os模块里面的相关功能,具体步骤如下:
- 导入os模块
import os
- 使用
os 模块相关功能
os.函数名()
文件重命名
os.rename(目标文件名, 新文件名)
删除文件
os.remove(目标文件名)
创建文件夹
os.mkdir(文件夹名字)
删除文件夹
os.rmdir(文件夹名字)
获取当前目录
os.getcwd()
改变默认目录
os.chdir(目录)
获取目录列表
os.listdir(目录)
10. 面向对象
面向对象就是将编程当成是一个事物,对外界来说,事物是直接使用的,不用去管他内部的情况。而编程就是设置事物能够做什么事。
在面向对象编程过程中,有两个重要组成部分:类 和 对象。
类和对象的关系:用类去创建一个对象。
10.1 类
类是对一系列具有相同特征和行为的事物的统称,是一个抽象的概念,不是真实存在的事物。
类比如是制造洗衣机时要用到的图纸,也就是说类是用来创建对象。
10.2 对象
对象是类创建出来的真实存在的事物,例如:洗衣机。
注意:开发中,先有类,再有对象。
注意:创建对象的过程也叫实例化对象。
self 指的是调用该函数的对象。
class Washer():
def wash(self):
print('我会洗衣服')
print(self)
haier1 = Washer()
print(haier1)
haier1.wash()
haier2 = Washer()
print(haier2)
注意:打印对象和self得到的结果是一致的,都是当前对象的内存中存储地址。
10.3 添加和获取对象属性
属性即是特征,比如:洗衣机的宽度、高度、重量…
对象属性既可以在类外面添加和获取,也能在类里面添加和获取。
类外面添加对象属性
对象名.属性名 = 值
haier1.width = 500
haier1.height = 800
类外面获取对象属性
对象名.属性名
print(f'haier1洗衣机的宽度是{haier1.width}')
print(f'haier1洗衣机的高度是{haier1.height}')
类里面获取对象属性
self.属性名
class Washer():
def print_info(self):
print(f'haier1洗衣机的宽度是{self.width}')
print(f'haier1洗衣机的高度是{self.height}')
haier1 = Washer()
haier1.width = 500
haier1.height = 800
haier1.print_info()
10.4 魔法方法
在Python中,__xx__() 的函数叫做魔法方法,指的是具有特殊功能的函数。
__init__()
思考:洗衣机的宽度高度是与生俱来的属性,可不可以在生产过程中就赋予这些属性呢?
__init__() 方法的作用:初始化对象。
class Washer():
def __init__(self):
self.width = 500
self.height = 800
def print_info(self):
print(f'洗衣机的宽度是{self.width}, 高度是{self.height}')
haier1 = Washer()
haier1.print_info()
注意:
__init__() 方法,在创建一个对象时默认被调用,不需要手动调用__init__(self) 中的self参数,不需要开发者传递,python解释器会自动把当前的对象引用传递过去。
带参数的__init__()
思考:一个类可以创建多个对象,如何对不同的对象设置不同的初始化属性呢?
答:传参数。
str()
当使用print输出对象的时候,默认打印对象的内存地址。如果类定义了__str__ 方法,那么就会打印从在这个方法中 return 的数据。
class Washer():
def __init__(self, width, height):
self.width = width
self.height = height
def __str__(self):
return '这是海尔洗衣机的说明书'
haier1 = Washer(10, 20)
print(haier1)
del()
当删除对象时,python解释器也会默认调用__del__() 方法。
class Washer():
def __init__(self, width, height):
self.width = width
self.height = height
def __del__(self):
print(f'{self}对象已经被删除')
haier1 = Washer(10, 20)
del haier1
10.5 继承
不由任意内置类型派生出的类,称之为经典类。
class 类名:
代码
......
class 类名(object):
代码
Python面向对象的继承指的是多个类之间的所属关系,即子类默认继承父类的所有属性和方法,具体如下:
class A(object):
def __init__(self):
self.num = 1
def info_print(self):
print(self.num)
class B(A):
pass
result = B()
result.info_print()
在Python中,所有类默认继承object类,object类是顶级类或基类;其他子类叫做派生类。
单继承
class Master(object):
def __init__(self):
self.kongfu = '[古法煎饼果子配方]'
def make_cake(self):
print(f'运用{self.kongfu}制作煎饼果子')
class Prentice(Master):
pass
daqiu = Prentice()
print(daqiu.kongfu)
daqiu.make_cake()
多继承
所谓多继承意思就是一个类同时继承了多个父类。
class Prentice(School, Master):
pass
注意:当一个类有多个父类的时候,默认使用第一个父类的同名属性和方法。
子类重写父类同名方法和属性
子类和父类具有同名属性和方法,默认使用子类的同名属性和方法。
子类调用父类的同名方法和属性
def make_cake(self):
self.__init__()
print(f'运用{self.kongfu}制作煎饼果子')
def make_master_cake(self):
Master.__init__(self)
Master.make_cake(self)
多层继承
故事:N年后,daqiu老了,想要把所有技术传承给自己的徒弟。
super()调用父类方法
class Master(object):
def __init__(self):
self.kongfu = '[古法煎饼果子配方]'
def make_cake(self):
print(f'运用{self.kongfu}制作煎饼果子')
class School(Master):
def __init__(self):
self.kongfu = '[黑马煎饼果子配方]'
def make_cake(self):+
print(f'运用{self.kongfu}制作煎饼果子')
super().__init__()
super().make_cake()
class Prentice(School):
def __init__(self):
self.kongfu = '[独创煎饼果子技术]'
def make_cake(self):
self.__init__()
print(f'运用{self.kongfu}制作煎饼果子')
def make_master_cake(self):
Master.__init__(self)
Master.make_cake(self)
def make_school_cake(self):
School.__init__(self)
School.make_cake(self)
def make_old_cake(self):
super().__init__()
super().make_cake()
daqiu = Prentice()
daqiu.make_old_cake()
注意:使用super() 可以自动查找父类。调用顺序遵循 __mro__ 类属性的顺序。比较适合单继承使用。
私有权限
定义私有属性和方法
在Python中,可以为实例属性和方法设置私有权限,即设置某个实例属性或实例方法不继承给子类。
设置私有权限的方法:在属性名和方法名 前面 加上两个下划线 __。
def __info_print(self):
print(self.kongfu)
print(self.__money)
daqiu = Prentice()
xiaoqiu = Tusun()
注意:私有属性和私有方法只能在类里面访问和修改。
获取和修改私有属性值
在Python中,一般定义函数名get_xx 用来获取私有属性,定义set_xx 用来修改私有属性值。
def get_money(self):
return self.__money
def set_money(self):
self.__money = 500
def make_master_cake(self):
Master.__init__(self)
Master.make_cake(self)
def make_school_cake(self):
School.__init__(self)
School.make_cake(self)
总结
10.6 面向对象-其他
面向对象三大特性
- 封装
- 将属性和方法书写到类的里面的操作即为封装
- 封装可以为属性和方法添加私有权限
- 继承
- 子类默认继承父类的所有属性和方法
- 子类可以重写父类属性和方法
- 多态
多态
多态指的是一类事物有多种形态,(一个抽象类有多个子类,因而多态的概念依赖于继承)。
- 定义:多态是一种使用对象的方式,子类重写父类方法,调用不同子类对象的相同父类方法,可以产生不同的执行结果
- 好处:调用灵活,有了多态,更容易编写出通用的代码,做出通用的编程,以适应需求的不断变化!
- 实现步骤:
- 定义父类,并提供公共方法
- 定义子类,并重写父类方法
- 传递子类对象给调用者,可以看到不同子类执行效果不同
体验多态
class Dog(object):
def work(self):
print('指哪打哪...')
class ArmyDog(Dog):
def work(self):
print('追击敌人...')
class DrugDog(Dog):
def work(self):
print('追查毒品...')
class Person(object):
def work_with_dog(self, dog):
dog.work()
ad = ArmyDog()
dd = DrugDog()
daqiu = Person()
daqiu.work_with_dog(ad)
daqiu.work_with_dog(dd)
类属性和实例属性
设置和访问类属性
- 类属性就是 类对象 所拥有的属性,它被 该类的所有实例对象 所共有。
- 类属性可以使用 类对象 或 实例对象 访问。
类属性的优点
- 记录的某项数据 始终保持一致时,则定义类属性。
- 实例属性 要求 每个对象 为其 单独开辟一份内存空间 来记录数据,而 类属性 为全类所共有 ,仅占用一份内存,更加节省内存空间。
修改类属性
类属性只能通过类对象修改,不能通过实例对象修改,如果通过实例对象修改类属性,表示的是创建了一个实例属性。
实例属性
class Dog(object):
def __init__(self):
self.age = 5
def info_print(self):
print(self.age)
wangcai = Dog()
print(wangcai.age)
wangcai.info_print()
类方法和静态方法
类方法特点
- 需要用装饰器
@classmethod 来标识其为类方法,对于类方法,第一个参数必须是类对象,一般以cls 作为第一个参数。
类方法使用场景
- 当方法中 需要使用类对象 (如访问私有类属性等)时,定义类方法
- 类方法一般和类属性配合使用
class Dog(object):
__tooth = 10
@classmethod
def get_tooth(cls):
return cls.__tooth
wangcai = Dog()
result = wangcai.get_tooth()
print(result)
静态方法
静态方法特点
- 需要通过装饰器
@staticmethod 来进行修饰,静态方法既不需要传递类对象也不需要传递实例对象(形参没有self/cls)。 - 静态方法 也能够通过 实例对象 和 类对象 去访问。
静态方法使用场景
- 当方法中 既不需要使用实例对象(如实例对象,实例属性),也不需要使用类对象 (如类属性、类方法、创建实例等)时,定义静态方法
- 取消不需要的参数传递,有利于 减少不必要的内存占用和性能消耗
class Dog(object):
@staticmethod
def info_print():
print('这是一个狗类,用于创建狗实例....')
wangcai = Dog()
wangcai.info_print()
Dog.info_print()
总结
@classmethod
def xx():
代码
@staticmethod
def xx():
代码
11. 异常
try:
可能发生错误的代码
except:
如果出现异常执行的代码
try:
print(num)
except NameError:
print('有错误')
注意:
- 如果尝试执行的代码的异常类型和要捕获的异常类型不一致,则无法捕获异常。
- 一般try下方只放一行尝试执行的代码。
当捕获多个异常时,可以把要捕获的异常类型的名字,放到except 后,并使用元组的方式进行书写。
try:
print(1/0)
except (NameError, ZeroDivisionError):
print('有错误')
捕获异常描述信息
try:
print(num)
except (NameError, ZeroDivisionError) as result:
print(result)
捕获所有异常
Exception是所有程序异常类的父类。
try:
print(num)
except Exception as result:
print(result)
异常的else
else表示的是如果没有异常要执行的代码。
try:
print(1)
except Exception as result:
print(result)
else:
print('我是else,是没有异常的时候执行的代码')
异常的finally
finally表示的是无论是否异常都要执行的代码,例如关闭文件。
自定义异常
在Python中,抛出自定义异常的语法为raise 异常类对象 。
class ShortInputError(Exception):
def __init__(self, length, min_len):
self.length = length
self.min_len = min_len
def __str__(self):
return f'你输入的长度是{self.length}, 不能少于{self.min_len}个字符'
def main():
try:
con = input('请输入密码:')
if len(con) < 3:
raise ShortInputError(len(con), 3)
except Exception as result:
print(result)
else:
print('密码已经输入完成')
main()
总结
try:
可能发生异常的代码
except:
如果出现异常执行的代码
else:
没有异常执行的代码
finally:
无论是否异常都要执行的代码
except 异常类型:
代码
except 异常类型 as xx:
代码
class 异常类类名(Exception):
代码
def __str__(self):
return ...
raise 异常类名()
except Exception...
12. 模块
测试模块
在实际开中,当一个开发人员编写完一个模块后,为了让模块能够在项目中达到想要的效果,这个开发人员会自行在py文件中添加一些测试信息.,例如,在my_module1.py 文件中添加测试代码。
def testA(a, b):
print(a + b)
testA(1, 1)
此时,无论是当前文件,还是其他已经导入了该模块的文件,在运行的时候都会自动执行testA 函数的调用。
解决办法如下:
def testA(a, b):
print(a + b)
if __name__ == '__main__':
testA(1, 1)
模块定位顺序
当导入一个模块,Python解析器对模块位置的搜索顺序是:
- 当前目录
- 如果不在当前目录,Python则搜索在shell变量PYTHONPATH下的每个目录。
- 如果都找不到,Python会察看默认路径。UNIX下,默认路径一般为/usr/local/lib/python/
模块搜索路径存储在system模块的sys.path变量中。变量里包含当前目录,PYTHONPATH和由安装过程决定的默认目录。
- 注意
- 自己的文件名不要和已有模块名重复,否则导致模块功能无法使用
使用from 模块名 import 功能 的时候,如果功能名字重复,调用到的是最后定义或导入的功能。
总结
import 模块名
from 模块名 import 目标
from 模块名 import *
import 包名.模块名
from 包名 import *
__all__ = [] :允许导入的模块或功能列表
如果一个模块文件中有__all__ 变量,当使用from xxx import * 导入时,只能导入这个列表中的元素。
导包注意:必须在__init__.py 文件中添加__all__ = [] ,控制允许导入的模块列表。
加油!
感谢!
努力!
|