一,开发环境配置及安装
1.环境安装及配置环境变量
- 下载地址:https://www.python.org/downloads/
- 下载安装后,要想在系统的任何一个目录中,使用python.exe需要配置环境变量。
- 测试是否安装成功。
2.安装PyCharm
- 下载地址:https://www.jetbrains.com/zh-cn/pycharm/
社区版:免费。
二,Python语言概述
注意事项:
- python程序默认是顺序执行的。
- python区分大小写。
- python语句不需要以;结束,但是如果写上也不会报错,通常我们都不写。
1.转义字符
转义字符 | 效果 |
---|---|
\t | 制表位 |
\n | 换行符 |
\r | 一个回车 |
" | 一个 " |
’ | 一个 ’ |
\ | 一个 \ |
回车效果演示:
print("段誉向西行,\r他虽不会武功") # 他虽不会武功
2.注释
- 单行注释
# print("Hello,World")
- 多行注释
格式:三个单引号==‘’‘注释文字’''或者三个双引号"““注释文字””"==。
'''多行注释'''
"""多行注释"""
- 文件编码声明注释:在文件开头加上编码声明,用于指定文件的编码格式。
# coding:编码
3.变量
3.1 type()
name = "张无忌"
age = 18
score = 88.2
is_male = True
# 使用type(object)函数查看数据类型
print(type(name))
print(type(age))
print(type(score))
print(type(is_male))
print(f"\"hello\"的数据类型是:{type("hello")}")
任何程序的执行都必须放入内存中。
3.2 全局变量和局部变量
- 全局变量:在整个程序范围内都可以访问,定义在函数外部,拥有全局作用域的变量。
- 局部变量:只能在其被声明的函数范围内访问,定义在函数内部,拥有局部作用域的变量。
n = 100 # 全局变量
def fun():
n = 200 # 局部变量
print(n)
fun() # 200
print(n) # 100
n = 100 # 全局变量
def fun():
global n # 全局变量
n = 200
print(n)
print(n) # 100
fun() # 200
print(n) # 200
4.格式化输出
前置知识:加号的使用。
# 加号的使用:
print(100 + 100) # 200,数字拼接为数字
print("100" + "100") # 100100,字符串拼接为字符串
# print(100 + "100") # 报错,unsupported operand type(s) for +: 'int' and 'str'
- %操作符。
print("个人信息:%s %d" % (name,age))
- format()函数。
print("个人信息:{} {} {}".format(name,age,gender))
- f-strings。
print(f"个人信息:{name} {age} {gender}")
5.数据类型
5.1整型
- python语言有十进制,二进制,八进制,十六进制。
- 无论数字有多小,在python中也是要占用28个字节。python字节数随着数字的增大而增大,每次所占用字节的增长幅度为4个字节。
n1 = 8
n2 = 8 ** 8
n3 = 8 ** 88
n4 = 8 ** 888
n5 = 8 ** 2222
print(n1,sys.getsizeof(n1),type(n1))
print(n2,sys.getsizeof(n2),type(n2))
print(n3,sys.getsizeof(n3),type(n3))
print(n4,sys.getsizeof(n4),type(n4))
print(n5,sys.getsizeof(n5),type(n5))
- sys.getsizeof(object) 用于获取变量所占用的字节数量。
- 使用type(object)函数查看数据类型。
5.2浮点型
# 1.浮点型的表示方式
n1 = 4.5
n2 = 4.5e+2 # 科学计数法,表示4.5 * 10 ^ 2
n3 = 4.5e-2 # 科学计数法,表示4.5 / 10 ^ 2
print(n1)
print(n2)
print(n3)
# 2.浮点数的大小范围
print(sys.float_info)
# 3.浮点数的精度丢失问题
n4 = 8.1 / 3
print(n4) # 2.6999999999999997
# 解决方案:使用Decimal类
from decimal import Decimal
n4 = Decimal("8.1") / Decimal("3")
print(n4) # 2.7
5.3布尔型
- python中会将True视为1,False视为0。
print(False + 10) # 10
print(True + 10) # 11
- 在python中非0被视为真值,0被视为假值。
5.4字符串
- 使用引号(’ 或 ")包括起来,创建字符串。
- python不支持字符类型,单字符在python中也是作为一个字符串使用。
- 使用"""或’''输出,可以保持原来的格式。
- 在字符串前加入r,转义字符将不会转义。
print('Tom说"哈哈"')
print("Jack说'哈哈'")
print("""n1 = 8
n2 = 8 ** 8
n3 = 8 ** 88
n4 = 8 ** 888""")
print(r"\n")
5. 字符串驻留机制
- 字符串驻留机制:Python仅保存一份相同且不可变的字符串。不同的值被存放在字符串驻留池中,Python的驻留机制会对相同的字符串只保留一份拷贝,后续创建相同字符串时,不会开辟新空间,而是把该字符串的地址赋给新创建的变量。
- 内存图示:
- 驻留机制发生的几种情况:
- 字符串是由26个英文字母的大小写,0-9,_组成。
- 字符串的长度为0或者1时。
- 字符串在编译时进行驻留,而非运行时。
- [-5,256]的整数数字。
- PyCharm对字符串进行了优化处理。
str1 = "abc#"
str2 = "abc#"
print(id(str1) == id(str2)) # True
num1 = -6
num2 = -6
print(id(num1) == id(num2)) # True
- 字符串驻留机制的好处:当需要值相同的字符串时,可以直接从字符串池里拿来使用,避免频繁的创建与销毁,提升效率和节约内存。
6.数据类型转换
1.隐式类型转换
- python变量的类型不是固定的,会根据变量当前值在运行时决定的,可以通过内置函数type(变量)来查看其类型,这种方式就是隐式转换(自动转换)。
var1 = 10
print(type(var1)) # int
var1 = 1.1
print(type(var1)) # float
var1 = "哈哈"
print(type(var1)) # str
- 在运算的时候,数据类型会向高精度自动转换。
var2 = 10
var3 = 1.2
var4 = var2 + var3
print("var4 = ",var4,"var4的类型是:",type(var4)) # 11.2 float
2.显式(强制)类型转换
- 如果需要对变量数据类型进行转换,只需要将数据类型作为函数名即可,这种方式就是显示转换/强制转换。
- 函数会返回一个新的对象/值,这就是强制类型转换的结果。函数不会改变传入对象的值。
3.显式类型转换注意事项
- 不管什么值的int,float都可以转换为str,str(x)将对象x转换为字符串。在python中万事万物皆对象,包括int,float等等。
- int转成float时,会增加小数部分,比如123->123.0,float转成int时,会去掉小数部分,比如123.65->123。
- str转int,float使用int(x),float(x) 将对象 x 转换为int/float。要求字符串本身是可以转换为int/float的。否则会出现ValueError,程序就会终止。
var = "哈哈"
int(var)
- 练习:
i = 10
j = float(i)
print(type(i)) # int
print(type(j)) # float
i = j + 1
print(type(i)) # float
print(type(j)) # float
print(i) # 11.0
print(int(i)) # 11
print(type(i)) # float
7.运算符
7.1算术运算符
运算符 | 运算 | 范例 | 结果 |
---|---|---|---|
/ | 除 | 9/3 | 3.3333 |
% | 取模(取余) | 7%5 | 2 |
// | 取整除-返回商的整数部分(向下整除) | 9//2 | 4 |
** | 返回x的y次幂 | 2**4 | 16 |
- 对于除号 / ,返回结果是小数。
- 对于取整除 // ,返回商的整数部分(向下整除)。
- 当对一个数取模时,对应的运算公式:a % b = a -a // b * b。
# a % b = a - a // b * b
# 10 % 3 = 10 - 10 // 3 * 3 = 10 - 3 * 3 = 1
print(10 % 3) # 1
# 5 % -2 = 5 - 5 // (-2) * (-2) = 5 - (-3) * (-2) = 5 - 6 = -1
print(5 % -2) # -1
7.2比较运算符
运算符 | 效果 |
---|---|
is | 判断两个变量引用对象是否为同一个 |
is not | 判断两个变量引用对象是否不同 |
- 比较运算符的结果要么是True,要么是False。
a = 9
b = 8
print(a > b) # T
print(a >= b) # T
print(a <= b) # F
print(a < b) # F
print(a == b) # F
print(a != b) # T
flag = a > b
print("flag =",flag) # T
print(a is b) # F
print(a is not b) # T
7.3逻辑/布尔运算符
以下假设变量a为10,b为20。
运算符 | 逻辑表达式 | 描述 | 实例 |
---|---|---|---|
and | x and y | 布尔“与”:如果x为False,x and y 返回x的值,否则返回y的计算值 | (a and b)返回20 |
or | x or y | 布尔“与”:如果x为True,x or y 返回x的值,否则返回y的计算值 | (a or b)返回10 |
not | not x | 布尔“非”:如果x为True,返回False。如果x为False,它返回True。 | not (a and b)返回False |
a = 10
b = 20
print(a and b) # 20
print(a or b) # 10
print(not (a and b)) # False
- and是种“短路运算符”,只有当第一个为True时才去验证第二个。
- or是种“短路运算符”,只有当第一个为False时才去验证第二个。
- 在python中,非0被视为真值,0值被视为假值。
7.4赋值运算符
运算符 | 描述 | 实例 |
---|---|---|
**= | 复合幂赋值运算符 | c**=a等价于c = c ** a |
//= | 复合整除赋值运算符 | c//=a等价于c = c // a |
- python中交换两个变量值的三种方法:
# 方式一:通过中间变量
a = 10
b = 20
print("交换前,a = {},b = {}".format(a,b))
temp = a
a = b
b = temp
print("交换后,a = {},b = {}".format(a,b))
# 方式二:python特有语法
a = 10
b = 20
print("交换前,a = {},b = {}".format(a,b))
a,b = b,a
print("交换后,a = {},b = {}".format(a,b))
# 方式三:算法
a = 10
b = 20
print("交换前,a = {},b = {}".format(a,b))
a = a + b
b = a - b
a = a - b
print("交换后,a = {},b = {}".format(a,b))
7.5三元运算符
- python是一种极简主义的编程语言,它没有引入? : 这个运算符,而是使用if else关键字来实现相同的功能。
- 语法:max = a if a > b else b。
num1 = 10
num2 = -2
num3 = 38
max = (num1 if num1 > num2 else num2) if (num1 if num1 > num2 else num2) > num3 else num3
print(f"max = {max}")
7.6位运算符
- 二/八/十六进制转十进制:按权展开求和。
- 十进制转二/八/十六进制:除二/八/十六取余倒叙法。
- 二进制转八进制:从低位开始,将二进制数每三位一组,转成对应的八进制数即可。
- 二进制转十六进制:从低位开始,将二进制数每四位一组,转成对应的十六进制数即可。
- 原码,反码,补码:
- 二进制的最高位是符号位:0表示正数,1表示负数。
- 正数的原码,反码,补码都一样(三码合一)。
- 负数的反码 = 它的符号位不变,其他位取反。
- 负数的补码 = 它的反码 + 1,负数的反码 = 负数的补码 - 1。
- 0的反码,补码都是0。
- 在计算机运算的时候,都是以补码的方式来运算的。
- 当我们看运算结果的时候,要看它的原码。
假定用一个字节来表示:
3 => 原码:0000 0011
反码:0000 0011
补码:0000 0011
-3 => 原码:1000 0011
反码:1111 1100
补码:1111 1101
1 + 3 => 1的补码:0000 0001
3的补码:0000 0011
————————————————————
0000 0100(补码)=> 原码:0000 0100(4)
1 - 3 => 1的补码:0000 0001
-3的补码:1111 1101
————————————————————
1111 1110(补码) => 反码:1111 1101 => 原码:1000 0010(-2)
7.7运算符的优先级
7.8标识符
- python对各种变量,函数和类等命名时使用的字符序列成为标识符。
- 标识符命名规则(必须遵守):
- 由26个英文字母大小写,0-9,_组成。
- 数字不可以开头,开头必须是字母或下划线。
- 不可以使用关键字,但能包含关键字。
- python区分大小写。
- 命名规范(非必须遵守):
- 变量名:变量要小写,若有多个单词,使用下划线分开。常量要全部大写。
- 函数:函数名一律小写,如果有多个单词,用下划线隔开。另外,私有函数以双下划线开头。
- 类名:使用大驼峰命名,如:MyName。
def my_func(var1,var2)
pass
def __private_func(var1,var2)
pass
8.数据输入
- input(prompt)读入的类型为str。
name = str(input("请输入姓名:"))
age = int(input("请输入年龄:"))
score = float(input("请输入成绩:"))
print("\n您输入的信息如下:")
print("姓名:{},类型为:{}".format(name,type(name)))
print("年龄:{},类型为:{}".format(age,type(age)))
print("成绩:{},类型为:{}".format(score,type(score)))
9.流程控制
9.1顺序控制
9.2分支控制
- Python缩进非常重要,是用于界定代码块的,相当于其他编程语言里的大括号。
- 最短的缩进对较长的缩进有包含关系,缩进前后没有要求,但是每个代码块应具有相同的缩进长度。
9.3循环控制
9.3.1 for语句
- for语句基本语法:
for <变量> in <范围/序列>:
<循环操作语句>
- for基本语法说明:
- for,in是关键字,是规定好的。
- <范围/序列>可以理解要处理的数据集,需要是可迭代的对象(比如字符串,列表等)
- python中的for循环是一种“轮询机制”,是对指定的数据集,进行“轮询处理”。
- 循环时,依次将序列中的值取出赋给变量。
- 如需要遍历数字序列,可以使用内置range()函数,它会生成数列。range()生成的数列是前闭后开。
- range()的使用:
- for-else语法说明:
# 进入else的情况:for循环正常完成遍历,在遍历过程中,没有被打断(比如:没有执行到break语句)。
for <variable> in <sequence> :
<statements>
else:
<statements>
- 内存分析法(for语句执行):
9.3.2 while语句
- while语句基本语法:
while condition:
statements
- while-else语法:
# 在while...else判断条件为false时,会执行else的语句块,即:在遍历过程中,没有被打断(比如:没有执行到break语句)。
while condition:
statements
else:
additional_statements
10.函数
- 基本语法:
- 调用机制:
- 注意事项和使用细节:
- 如果同一个文件,出现两个函数名相同的函数,则以就近原则进行调用。
- 调用函数时,根据函数定义的参数位置来传递参数,这种传参方式就是位置参数,传递的实参和定义的形参顺序和个数必须一致,同时定义的形参,不用指定数据类型,会根据传入的实参类型决定。
- 函数可以有多个返回值,返回数据类型不受限制。
- 函数支持关键字参数,即:函数调用时,可以通过“形参名=实参值”形式传递参数。这样可以不受参数传递顺序的限制。
- 函数支持默认参数/缺省参数。默认参数,需要放在参数列表后。
- 函数支持可变参数/不定长参数,应用于调用函数时,不确定传入多少个实参的情况。传入的多个参数会组成一个元组(tuple)。
- 函数的可变参数/不定长参数,还支持多个关键字参数,也就是多个”形参名=实参值“。传入的多个参数会组成一个字典(dict)。
def cry():
print("cry()..hi...")
def cry():
print("cry()..ok...")
# python中不存在函数的重载
# 输出:cry()..ok...
cry()
def f2(n1,n2):
return n1+n2,n1-n2
r1,r2 = f2(10,20)
# 输出:r1->30 r2->-10
print(f"r1->{r1} r2->{r2}")
# 函数支持可变参数/不定长参数
def sum(*args):
# args的类型为tuple
total = 0
for ele in args:
total += ele
return total
result = sum(1,2,3,100)
# 函数支持关键字可变参数
def person_info(**args):
# args的类型为dict
for arg_name in args:
print(f"参数名->{arg_name} 参数值->{args[arg_name]}")
person_info(name="tom", age=18, email="tom@qq.com")
- 将函数作为参数传递:
def get_max(num1,num2):
return num1 if num1 >= num2 else num2
def myfun(fun,num1,num2):
return fun(num1,num2)
print(get_max(20,38))
print(myfun(get_max,20,38))
- lambda匿名函数:
- def关键字,可以定义有名称的函数,这个函数可以重复的使用。
- lambda关键字,可以定义匿名函数(无名称),匿名函数只能使用一次。
- 匿名函数用于临时创建一个函数,只使用一次的场景。
- 匿名函数的基本语法:
- lambda 形参列表: 函数体(一行代码)
- lambda关键字,表示定义匿名函数。
- 函数体:完成的功能,只能写一行,不能写多行代码。
- 匿名函数不需要return,运算结果就是返回值。
def myfun(fun,num1,num2):
return fun(num1,num2)
print(myfun(lambda num1,num2: num1 if num1 >= num2 else num2,20,38))
11.数据容器(Collections)
- 数据容器中存放的数据可以是任意类型。
11.1 列表(list)
- 列表的元素可以有多个,而且数据类型没有限制,允许有重复元素,并且是有序的。
- 反向索引:索引也可以从尾部开始,最后一个元素的索引为-1,往前一位为-2,以此类推。
- 列表生成式:
# 列表生成式
# 基本语法 [列表元素的表达式 for 自定义变量 in 可迭代对象]
list1 = [ele*2 for ele in range(1,5)]
# [2, 4, 6, 8]
print(list1)
list2 = [ele+ele for ele in "Java"]
# ['JJ', 'aa', 'vv', 'aa']
print(list2)
list3 = [ele*ele for ele in range(1,11)]
# [1, 4, 9, 16, 25, 36, 49, 64, 81, 100]
print(list3)
- 列表的元素是可以修改的,修改后,列表变量指向地址不变,只是数据内容变化。
list_color = ["red","green","white","grey","black"]
index = 0
while index < len(list_color):
print(list_color[index])
index += 1
print("-----------------------------")
for i in range(len(list_color)):
print(list_color[i])
print("-----------------------------")
for element in list_color:
print(element)
# 更新 ['purple', 'green', 'white', 'grey', 'black']
list_color[0] = "purple"
print(list_color)
# 添加 ['purple', 'green', 'white', 'grey', 'black', 'yellow']
list_color.append("yellow")
print(list_color)
# 删除 ['purple', 'green', 'white', 'grey', 'black']
del list_color[-1]
print(list_color)
11.2 元组(tuple)
- 元组可以存放多个不同类型数据,元组是不可变序列。元组的不可变是指当你创建元组的时候,它就不能改变了,也就是说它也没有append(),insert()这样的方法,但它也有获取某个索引值的方法,但不能重新赋值。
- 元组的元素可以有多个,而且数据类型没有限制(甚至可以嵌套元组),允许有重复元素,并且是有序的。
- 元组的内容不可以修改,但是可以修改元组内list的内容。
- 定义只有一个元素的元组,需要带上逗号,否则就不是元组类型。
- 为什么有了列表,python设计还要搞一个元组?
11.3 字符串(str)
- 在Python中处理文本数据是使用str对象,也成为字符串。字符串是由Unicode码位构成的不可变序列。
- ord()返回单个字符对应的Unicode编码值。
- chr()返回码值对应的字符。
- 字符串字面值的三种写法:
- 字符串是不可变序列,不能修改。
str = "hello world"
str[0] = "s" # str不能修改,地址不发生变化,不允许
str = "abc" # 地址发生变化,允许
- 在Python中,字符串的长度没有限制,取决于计算机内存的大小。
- 在Python中,字符串可以比较大小,比较规则类似于C语言中的strcmp。
- 切片:从一个序列中,取出一个子序列。
- 序列:内容连续,有序,可使用索引的一类数据容器。
# 基本语法:序列[起始索引:结束索引:步长],起始索引默认为0,结束索引默认截取到结尾,步长默认为1
str="hello world"
# 切片操作并不会影响原序列,而是返回了一个序列
slice1 = str[0:6:1]
print(slice1) # hello
# 步长为负数,表示反向取,同时注意起始索引和结束索引也要反向标记
slice2 = str[-1:-6:-1]
print(slice2) # dlrow
slice2 = str[-1:-6:-2]
print(slice2) # drw
11.4 集合(set)
- 集合是由不重复元素组成的无序容器。
- 不重复元素:集合中不会有相同的元素。
- 无序:集合中元素取出的顺序,和定义时元素顺序并不能保证一致。
- 创建空集合只能用set(),不能用{},{}创建的是空字典。
- 集合中不支持索引,所以对集合进行遍历,只能用for,不能用while。
- 集合底层会按照自己的一套算法来存储和取数据,所以每次取出顺序是不变的。
- 集合生成式:
# 集合生成式基本语法:{集合元素表达式 for 自定义变量 in 可迭代对象}
set1 = {ele*2 for ele in range(1,5)}
print(set1)
set2 = {ele+ele for ele in "韩曙平"}
print(set2)
11.5 字典(dict)
- 字典是一种映射类型,Key–Value的映射关系。字典的key必须是唯一的,如果指定了多个相同的key,后面的键值对会覆盖前面的。
- 字典的遍历:
dict_a = {'one': 1,'two': 2,'three': 3}
# 遍历方式一:依次取出key,在通过dict[key]取出对应的value
for key in dict_a:
print(f"key为{key},value为{dict_a[key]}")
# 遍历方式二:依次取出value
for value in dict_a.values():
print(value)
# 遍历方式三:依次取出key-value
for key,value in dict_a.items():
print(f"key:{key},value:{value}")
- 创建空字典可以通过dict()或{}。
- 字典生成式:
# 字典生成式
# 基本语法:{字典key的表达式:字典value的表达式 for 表示key的变量,表示value的变量 in zip(可迭代对象,可迭代对象)}
books = ["红楼梦","西游记","三国演义","水浒传"]
authors = ["曹雪芹","吴承恩","罗贯中","施耐庵"]
dict_b = {key:value for key,value in zip(books,authors)}
# {'红楼梦': '曹雪芹', '西游记': '吴承恩', '三国演义': '罗贯中', '水浒传': '施耐庵'}
print(dict_b)
11.6 小结
12.传参机制
12.1 字符串和数值类型传参机制
- 字符串和数值类型传参机制:
- 字符串和数值类型是不可变数据类型,当对应的变量的值发生了变化时,它对应的内存地址会发生改变。
- 字符串和数值类型是不可变数据类型,当对应的变量的值发生了变化时,它对应的内存地址会发生改变。
12.2 list,tuple,set,dict的传参机制
12.3 小结
- Python数据类型主要有:int,float,bool,str,list,tuple,set,dict。分为可变数据类型和不可变数据类型。
- 可变数据类型:当该数据类型的变量的值发生了改变,如果它的内存地址不变,那么这个数据类型就是可变数据类型。(list,set,dict)
- 不可变数据类型:当该数据类型的变量的值发生了改变,如果它的内存地址也发生了变化,那么这个数据类型就是可变数据类型。(int,float,bool,str, tuple)
13.模块
- 模块:模块是一个py文件,后缀名为.py。模块可以定义函数、类和变量,模块里也可能包含可执行的代码。
- 模块导入:
# import语句通常写在文件开头
# 1.导入一个或多个模块
"""
import 模块
import 模块1,模块2
import math,random
"""
# 2.导入模块的指定功能
"""
from 模块 import 函数,类,变量...
from math import fabs
"""
# 3.导入模块的全部功能
"""
from 模块 import *
from math import *
"""
# 4.给导入的模块或功能取别名
"""
from 模块 import 函数,类,变量... as 别名
from math import fabs as fa
"""
- 注意事项:
- 使用__name__可以避免模块中测试代码的执行。
- 使用__all__可以控制import *时,哪些功能被导入。注意:import 模块,不受__all__的限制。
# module文件
def fun1():
print("fun1()")
def fun2():
print("fun2()")
# 避免运行主程序后,测试代码的加载
if __name__ == "__main__":
print("测试代码")
# main文件
import module
print("主程序代码")
module.fun1()
module.fun2()
# module文件
__all__ = ['fun1']
def fun1():
print("fun1()")
def fun2():
print("fun2()")
# main文件
from module import *
fun1()
# 报错,module文件中限制使用fun2()
# fun2()
14.包
14.1 pip的使用
- 进入到命令控制台。
- pip install 库名/包名
- 注意:pip是通过网络安装的,需要网络是连通的。
14.2 指定pip源
三,面向对象
1.类和对象
class Cat:
# None是Python的内置常量,通常被用来代表空值的对象
# None是NoneType类型的唯一实例
name = None # 姓名属性
age = None # 年龄属性
color = None # 颜色属性
xb_cat = Cat()
xb_cat.name = "小白"
xb_cat.age = 2
xb_cat.color = "白色"
print(f"姓名:{xb_cat.name},颜色:{xb_cat.color},年龄:{xb_cat.age}")
-
内存解析:
-
对象的传递机制:
-
对象的传参机制:
-
对象的布尔值:
2.成员方法
# 定义成员方法的基本语法:
"""
def 方法名(self,形参列表):
方法体
1.在方法定义的参数列表中,有一个self
2.self是定义成员方法时,需要写上的
3.self表示当前对象本身
4.当我们通过对象调用方法时,self会隐式传入
5.在方法内部,需要使用self,才能访问到成员变量
"""
class Person:
name = None
age = None
def hi(self):
print("hi, python")
def cal01(self):
sum = 0
for i in range(1, 1001, 1):
sum += i
return sum
def cal02(self, n):
sum = 0
for i in range(1, n + 1, 1):
sum += i
return sum
def get_sum(self, num1, num2):
return num1 + num2
p = Person()
p.hi()
p.cal01()
- Python支持对象动态添加方法。
def hi():
print("hi,python")
class Person:
name = None
def ok(self):
print("ok")
p1 = Person()
p2 = Person()
# 为p1对象动态添加hi(),只针对p1
p1.m1 = hi
p1.m1()
# 报错,p2无m1()
# p2.m1()
# <class 'function'> 动态添加的方法类型为:function
print(type(p1.m1))
# <class 'method'> 成员方法类型为:method
print(type(p1.ok))
3.self
- 在方法定义的参数列表中,有一个self。
- 在方法内部,要访问成员变量和成员方法,需要使用self。
- self是定义成员方法时,需要写上的,如果不写,则需要使用@staticmethod标注,否则会报错。
- 通过@staticmethod可以将方法转为静态方法。
- 静态方法,可以不带self。
- 静态方法调用方式:①对象调用,②类名调用。
class Person:
name = None
age = None
def compare_to(self,other):
if id(self) == id(other):
return True
if self.age == other.age and self.name == other.name:
return True
return False
p1 = Person()
p1.name = "张无忌"
p1.age = 18
p2 = Person()
p2.name = "张无忌"
p2.age = 17
print(p1.compare_to(p2))
p2.age = 18
print(p1.compare_to(p2))
4.构造方法
"""
构造方法基本语法:
def __init__(self,参数列表):
代码
1.在初始化对象时,会自动执行__init__方法
2.构造方法完成对象的初始化任务
3.一个类中只有一个__init__方法,即使写了多个,也只有最后一个生效
4.构造方法不能有返回值
5.Python支持动态生成对象属性
"""
class Person:
name = None
def __init__(self,name,age):
print(f"地址为:{id(self)}的对象进行初始化……")
self.name = name
# Python支持动态生成对象属性
self.age = age
p1 = Person("张三",18)
print(f"{p1.name} {p1.age}")
5.面向对象三大特征
5.1封装性
- 封装:把抽象出来的数据和对数据的操作封装在一起,数据被保护在内部。
- 类中的变量或方法以双下划线__命名开头,则该变量或方法为私有的,私有的变量或方法,只能在本类内部使用,类的外部无法使用。
- 默认情况下,类中的变量和方法都是公有的,它们的名称前都没有下划线。公共的变量和方法,在类的外部和内部都可以正常访问。
class Clerk:
name = None
__job = None
__salary = None
def __init__(self, name, job, salary):
self.name = name
self.__job = job
self.__salary = salary
def set_job(self, job):
self.__job = job
def get_job(self):
return self.__job
def set_salary(self, salary):
self.__salary = salary
def get_salary(self):
return self.__salary
- Python语言动态特性,会出现伪私有属性的情况。
"""
Python语言动态特性,会出现伪私有属性的情况。
Python语言动态特性,会动态创建属性__job,但这个属性
和我们在类中定义的私有属性__job并不是同一个变量,我们在类中定义的__job私有属性完整的名字为_Clerk__job
"""
clerk = Clerk("张三", "Python工程师", 8000)
print(clerk.get_job()) # Python工程师
clerk.__job = "Go工程师"
print(clerk.__job) # Go工程师
5.2继承性
- 子类继承了父类所有的属性和方法,非私有的属性和方法可以在子类直接访问,但是私有属性和方法不能在子类中直接访问,要通过父类提供公共的方法去访问。
- Python语言中,object是所有类的基类。在pyCharm中,通过ctrl + h查看继承关系。
- Python支持多重继承。
- 在多重继承中,如果有同名的成员,遵守从左到右的继承优先级(即:写左边的父类优先级高,写在右边的父类优先级低)。