Python纯基础笔记,本人复习Python知识点

Python纯基础笔记,本人复习Python知识点

1:解释器和编译器

计算机不能直接理解任何机器语言以外的语言,将其它语言翻译成机器语言的工具就叫编译器。
编译器翻译的方式有两种:一是编译,另外一个是解释。两种方式的区别在于翻译时间节点的不同。当编译器以解释方式运行的时候,也称之为解释器。
编译型语言源代码经过编译器,生成最终可执行的文件,交付操作系统,再由操作系统交付给CPU;解释型语言源代码交付解释器,由解释器逐行解释每一句源代码,解释一句执行一句。
编译型语言:程序在执行之前需要有一个专门的编译过程,把程序编译成为机器语言的文件,运行时不需要重新翻译,直接使用编译的结果就行了,程序执行效率高,依赖编译器,跨平台性能差些,速度更快,如C,C++。
解释型语言:解释型语言编写的程序不能进行预先编译,以文本方式存储程序代码,会将代码一句一句直接运行。在运行程序时,必须先解释再运行。解释型语言的跨平台性更好,但速度相对差些。

2:Python特点

1:Python是完全面向对象的语言:
函数、模块、数字、字符串都是对象,在Python中一切皆对象;
完全支持继承、重载、多重继承;
支持重载运算符,也支持泛型设计;
2:Python拥有一个强大的标准库,Python语言的核心只包含数字、字符串、列表、字典文件等常见类型和函数,而由Python标准库提供了系统管理、网络通信、文本处理、数据库接口、图形系统、XML处理等额外功能;
3:Python社区提供了大量第三方模块,使用方式与标准库类似。他们的功能覆盖科学计算、人工智能、机器学习、web开发、数据库接口、 图形系统多个领域。

3:算术运算符

+、-、*、/、//取整除、%取余数、**幂
在Python中,*运算符还可以用于字符串,计算结果就是字符串重复指定次数的结果。如’-’ * 50,输出50个’-’;
同级运算符是从左至右计算;
可以用()调整计算的优先级;
使用交互式方式,如果查看变量内容,直接输入变量名即可,不需要使用print函数;
使用解释器执行,如果输出变量的内容,要用print(变量名);
Python可以根据等号右侧的值,自动推导出变量中存储数据的类型,所以在Python中定义变量时不需要指定类型;
数据类型可以分为数字型和非数字型;
数字型:整型int,浮点型float,布尔型bool(非0即真),复数型complex(主要用于科学计算)
非数字型:字符串string,列表list,元组tuple,字典dict
使用type()函数可以查看一个变量的类型。
不同类型变量之间的计算:
(1)数字型变量之间可以直接计算
如果变量时bool型的,在计算时True对应的数字是1,False对应的数字是0;
(2)字符串变量之间使用’+'拼接字符串,拼接字符串的方法有五种:
"+"号;
直接连接 s= “hello”“world”;
用逗号,连接 print(“hello”, “world”);
格式化字符 s= “%s %s” % (s1, s2);
join函数 s= " “.join([s1, s2]),输出hello world,中间有空格;
标准输出的重定向
(3)字符串变量可以和整数使用”*"重复拼接相同的字符串;
(4)数字型变量和字符串之间不能进行其他计算;
但将数字型变量用str()方法转化为字符串就可进行计算。

s1 = "hello"
n = 20
s = s1 + str(n)
print(s)
# 输出结果为:hello20
V = 12.88
b = True
print(s1 + str(n) + str(V) + str(b))
# 输出结果为:hello2012.88True

或者格式化:

s = "%s %d %.2f" % (s1, n ,V)
# 输出为:hello 20 12.88
4:格式化字符串
格式化字符串含义
%s字符串
%d有符号十进制整数,%06d表示输出的整数显示6位数,不足的地方用0补齐
%f浮点数,%.2f表示小数点后只显示两位
%%输出%
5:标识符

标识符是程序员定义的变量名、函数名;
标识符可以由字母、下划线和数字组成;
不能以数字开头;
不能与关键字重名;

6:关键字

关键字是在Python内部已经使用的标识符;

import keyword
print(keyword.kwlist)
# 查看Python中的关键字

Python中的标识符是区分大小写的

7:驼峰命名法

小驼峰命名法:第一个单词以小写字母开始,后续单词的首字母大写;
大驼峰命名法:每一个单词的首字母都采用大写字母,如FirstName

8:逻辑运算

逻辑运算符可以把多个条件按照逻辑进行连接,变成更复杂的条件。Python中的逻辑运算符包括:与and/或or/非not三种。
and:两个条件同时满足,返回True,只要有一个不满足,就返回False;
or:两个条件只要有一个满足,返回True,两个条件都不满足,返回False;
not:

a = False
if not a:   (这里因为a是False,所以not a就是True,等于if True,所以会输出hello)
    print("hello")

random库:random.choice([“剪刀, 石头,布”]),从列表中随机选择一项
random.randint(a, b),返回[a,b]之间的整数,包括a和b
random.randint(20,20),返回结果永远为20
random.randint(20,10),错误写法

9:运算符

算术运算符:+ - * / // % **
比较(关系)运算符 == != > < >= <=
逻辑运算符 and or not
赋值运算符
运算符的优先级
赋值运算符:

赋值运算符实例
=c=a+b
+=c+=a等价于c=c+a
-=c-=a
*=c*=a
/=c/=a
//=c//=a
%=c%=a
**=c**=a

运算符的优先级:
由高到低:
**(幂运算符)
* / % // (乘、除、取余数、取整除)
+ - (加减)
<= < >= > (比较运算符)
== != (等于运算符)
= %= /= //= -= += *= **= (赋值运算符)
not and or (逻辑运算符)

循环

程序的三大流程:
顺序–从上向下,顺序执行代码
分支–根据条件判断,决定代码的分支
循环–让特定代码重复执行
除非需求的特殊要求,否则循环的计数都从0开始
break和continue:
break某一条件满足时,退出循环,不再执行后续重复的代码。
continue某一条件满足时,不执行本次循环中的后续代码,只跳过此次循环。
print()函数:
在默认情况下,print函数输出内容之后,会自动在内容末尾增加换行;
如果不希望末尾增加换行,可以在print函数输出内容的后面增加 print(“hello”, end="")
打印九九乘法表代码:

row = 1
while row <= 9:
	col = 1 # 每次外部循环开始前,都将col置为1
	while col <= row:
		print("%d * %d = %d " % (col, row, col*row))
		col +=1
	print("")
	row += 1

字符串中的转义字符:

转义字符描述
\反斜杠
单引号
"双引号
\n换行
\t横向制表符

\t 在控制台输出一个制表符,协助在输出文本时垂直方向保持对齐
\n 在控制台输出一个换行符

函数

函数:把具有独立功能的代码块组织为一个小模块;在需要的时候调用,函数的使用包含两个步骤:
定义函数–封装独立的功能
调用函数–享受封装的成果
函数的作用:在开发程序时,使用函数可以提高编写的效率以及代码的重用
函数名称的命名应该符合标识符的命名规则:
(1)可以由数字、下划线和数字组成
(2)不能以数字开头
(3)不能与关键字重名
函数的文档注释:
在开发中,如果希望给函数添加注释,应该在定义函数的下方,使用连续的三对引号。
**函数的参数:**参数可以增加函数的通用性,针对相同的数据处理逻辑,能够适应更多地数据:
(1)在函数内部,把参数当作变量使用,进行需要的数据处理
(2)函数调用时,按照函数定义的参数顺序,把希望在函数内部处理的数据,通过参数传递
形参和实参:
形参:定义函数时,小括号中的参数,是用来接受参数用的,在函数内部作为变量使用。
实参:调用函数时,小括号中的参数,是用来把数据传递到函数内部用的。
函数的返回值:
在程序开发的时候,会希望一个函数执行结束后,告诉调用者一个结果,以便调用者针对具体的结果做后续的处理。
返回值是函数完成工作后,最后给调用者的一个结果。
在函数中通过return关键字可以返回结果。注意,return表示返回,使用return返回后,return下方的属于这个函数的代码就不会执行了。
**模块:**模块是Python程序架构的一个核心概念:
(1)模块就好比是工具包,要想使用这个工具包中的工具,就需要导入这个模块
(2)每一个以扩展名py结尾的Python源代码文件都是一个模块
(3)在模块定义的全局变量,函数都是模块能够提供给外界直接使用的工具
面试题:
设置Python模块的搜索路径有几种方式:
(1)设置PYTHONPATH环境变量
(2)添加.pth文件
(3)通过sys.path设置路径
(4)如果使用Pycharm,可以直接设置搜索路径
永久设置Python模块搜索路径有几种方式,如何让使用他们:
(1)设置PYTHONPATH环境变量
(2)添加.pth文件
(3)如果使用Pycharm,可以直接设置搜索路径
临时设置Python模块搜索路径有几种方式,如何让使用他们:
(1)通过sys.path设置路径
(2)临时设置PYTHONPATH
模块名也是一个标识符:
(1)标识符可以由字母、下划线和数字组成
(2)不能以数字开头
(3)不能与关键字重名
注意:如果在给Python文件起名时,以数字开头是无法在Pycharm中通过import导入这个模块的
.pyc文件:
(1)浏览程序目录会发现一个__pycache__的目录
(2)目录下会有一个helloworld.cpython-37.pyc文件,cpython-37表示python解释器的版本
(3)这个pyc文件是由Python解释器将模块的源码转换为字节码,Python这样保存字节码是作为一种启动速度的优化
字节码:
(1)Python在解释源程序时是分成两个步骤的:首先处理源代码,编译生成一个二进制字节码;再对二进制字节码进行处理,才会生成CPU能够识别的机器码
(2)有了模块的字节码文件之后,下一次运行程序时,如果上次保存字节码之后没有修改过源代码,Python将会加载.pyc文件并跳过编译这个步骤
(3)当Python重编译时,他会自动检查源文件和字节码文件的时间戳
(4)如果你修改了源代码,下次程序运行时,字节码将自动重新创建

高级变量类型

字符串、列表、元组、字典(非数字型)
在Python中,所有的非数字类型变量都支持以下特点:
(1)都是一个序列sequence,也可以理解为容器
(2)取值[]
(3)遍历for in
(4)计算长度、最大最小值、比较、删除
(5)连接+和重复*
(6)切片
列表:
(1)list列表是Python中使用最频繁的数据类型,在其他语言中通常叫做数组
(2)专门用来存储一串信息
(3)列表用[]定义,数据之间使用, 分隔
(4)列表的索引从0开始,索引就是数据在列表中的位置编号,索引又可以被称为下标
(5)从列表中取值时,如果超出索引范围,程序会报错
列表的增加:
list.insert(索引,数据) # 在指定位置插入数据,若数据是一个列表,则把列表当作整体插入到索引位置处
list.append(数据) # 在末尾追加数据,若数据是一个列表,则把列表当作整体插入到索引位置处
list.extend(列表2) #将列表2的数据追加到list,注意是将列表中的数据追加到list中
列表的修改:
list[0]=数据 # 修改指定索引的数据
列表的删除:
del list[索引] # 删除指定索引的数据
list.remove[数据] # 删除第一个出现的指定数据
list.pop # 删除末尾数据
list.pop[索引] # 删除指定索引的数据
list.clear # 清空列表
列表的统计:
len(list) # 列表长度
list.count(数据) # 数据在列表中出现的次数
列表的排序:
list.sort() # 默认升序排序
list.sort(reverse=True) # 降序排序
list.reverse() # 将列表的元素逆序排列
del关键字:
使用del关键字同样可以删除列表中的元素,del关键字本质上使用来将一个变量从内存中删除的,如果使用del关键字将变量从内存中删除,后续的代码就不能再使用这个变量了。在日常开发中,要从列表中删除数据,建议使用列表本身提供的方法
循环遍历:
遍历就是从头到尾依次从列表中获取数据,在循环体内部针对每一个元素执行相同的操作,在Python中为了提高列表的遍历效率,专门提供的迭代遍历,使用for实现迭代遍历。
循环遍历应用场景:
尽管Python的列表中可以存储不同类型的数据,但是在开发中,更多的应用场景是:
(1)列表存储相同类型的数据
(2)通过迭代遍历,在循环体内部,针对列表中的每一项元素,执行相同的操作
元组:
(1)元组与列表类似;不同之处在于元组的元素不能修改
(2)元组表示多个元素组成的序列
(3)元组在Python开发中,有特定的应用场景
(4)用于存储一串信息,数据之间使用,分隔
(5)元组用()定义
(6)元组的索引从0开始
(7)元组中只包含一个元素时,需要在元素后面添加逗号,tuple = (50, )
元组的常用操作:
tuple.count(数据) # 数据在元组中出现的次数
tuple.index(数据) # 获得数据第一次出现的索引
元组的循环遍历:
(1)取值就是从元组中获取存储在指定位置的数据
(2)遍历就是从头到尾依次从元组中获取数据
(3)在实际开发中,除非能够确认元组中的数据类型,否则针对元组的循环遍历需求并不是很多。
元组的应用场景:
尽管可以使用for in 遍历元组,但是在开发中,更多的应用场景是:
(1)函数的参数和返回值:return a, b这里实际上返回的是元组(a,b)只是可以省略括号,换句话说就是,一个函数可以接收任意多个参数,或者一次返回多个数据。
(2)格式化字符串:格式化字符串后面的()本质上就是一个元组
(3)把列表转化为元组,使列表不可以被修改,保护数据安全
列表与元组之间的转换:
(1)使用list函数可以把元组转换成列表list(元组)
(2)使用tuple函数可以把列表转换成元组tuple(列表)
字典(可修改):
(1)dictionary(字典)是除列表以外Python之中最灵活的数据类型
(2)字典同样可以用来存储多个数据,通常用于存储描述一个物体的相关信息
字典和列表的区别:
(1)列表是有序的对象集合
(2)字典是无序的对象集合
(3)字典用{}定义,列表用[]定义
(4)字典使用键值对存储数据,键值对之间使用,分隔,键key是索引,值value是数据,键和值之间使用 : 分隔,键必须是唯一的,值可以取任何数据类型
(5)len(字典) # 获取字典的键值对数量
(6)dict.keys() # 返回所有key列表
dict.values() # 所有value列表
dict.items() # 所有(key, value)元组列表
dict[key] # 可以从字典中取值,key不存在会报错
dict.get(key) # 可以从字典中取值,key不存在不会报错
del dict[key] # 删除指定的键值对,key不存在会报错
dict.pop(key) # 删除指定的键值对,key不存在会报错
dict.popitem[] # 随机删除一个键值对
dict.clear() # 清空字典
dict[key] = value # key存在,修改数据,key不存在,新建键值对
dict.setdefault(key, value) # key存在,不会修改数据,key不存在,新建键值对
dict.update(字典2) # 将字典2的数据合并到字典1
dict.clear .items .setdefault .copy .keys .update .fromkeys .pop .values .get .popitem
字典应用场景:
(1)尽管可以使用for in 遍历字典,但是在开发中,更多的应用场景是:
(2)使用多个键值对,存储一个物体的相关信息 – 描述更复杂的数据信息
(3)将多个字典放在一个列表中,再进行遍历,在循环体内部针对每一个字典进行相同的处理

card_list = [
	{"name":"张三"
	"qq":"12345"
	"age":18}
	{"name":"李四"
	"qq":"54321"
	"age":19}
	]
字符串

(1)字符串就是一串字符,是编程语言中表示文本的数据类型
(2)在Python中可以使用一对双引号""或者一对单引号’'定义一个字符串。若字符串内有字符串,则外层单引号内层双引号或者外层双引号内层单引号
(3)可以使用索引获取一个字符串中指定位置的字符,索引计数从0开始
(4)也可以使用for循环遍历字符串中的每一个字符
(5)len(str)获取字符串的长度,str.count(str1)返回str1在str中出现的次数,str[索引]返回索引位置的单个字符,str.index(str1)返回str1第一次出现的索引
判断类型:

方法说明
string.isspace()如果 string 中只包含空格,则返回 True
string.isalnum()如果 string 至少有一个字符并且所有字符都是字母或数字则返回 True
string.isalpha()如果 string 至少有一个字符并且所有字符都是字母则返回 True
string.isdecimal()如果 string 只包含数字则返回 True全角数字
string.isdigit()如果 string 只包含数字则返回 True全角数字\u00b2
string.isnumeric()如果 string 只包含数字则返回 True,全角数字汉字数字
string.istitle()如果 string 是标题化的(每个单词的首字母大写)则返回 True
string.islower()如果 string 中包含至少一个区分大小写的字符,并且所有这些(区分大小写的)字符都是小写,则返回 True
string.isupper()如果 string 中包含至少一个区分大小写的字符,并且所有这些(区分大小写的)字符都是大写,则返回 True

查找和替换:

方法说明
string.startswith(str)检查字符串是否是以 str 开头,是则返回 True
string.endswith(str)检查字符串是否是以 str 结束,是则返回 True
string.find(str, start=0, end=len(string))检测 str 是否包含在 string 中,如果 start 和 end 指定范围,则检查是否包含在指定范围内,如果是返回开始的索引值,否则返回 -1
string.rfind(str, start=0, end=len(string))类似于 find(),不过是从右边开始查找
string.index(str, start=0, end=len(string))跟 find() 方法类似,不过如果 str 不在 string 会报错
string.rindex(str, start=0, end=len(string))类似于 index(),不过是从右边开始
string.replace(old_str, new_str, num=string.count(old))把 string 中的 old_str 替换成 new_str,如果 num 指定,则替换不超过 num 次

大小写转换:

方法说明
string.capitalize()把字符串的第一个字符大写
string.title()把字符串的每个单词首字母大写
string.lower()转换 string 中所有大写字符为小写
string.upper()转换 string 中的小写字母为大写
string.swapcase()翻转 string 中的大小写

文本对齐:

方法说明
string.ljust(width)返回一个原字符串左对齐,并使用空格填充至长度 width 的新字符串
string.rjust(width)返回一个原字符串右对齐,并使用空格填充至长度 width 的新字符串
string.center(width)返回一个原字符串居中,并使用空格填充至长度 width 的新字符串

去除空白字符:

方法说明
string.lstrip()截掉 string 左边(开始)的空白字符
string.rstrip()截掉 string 右边(末尾)的空白字符
string.strip()截掉 string 左右两边的空白字符

拆分和连接:

方法说明
string.partition(str)把字符串 string 分成一个 3 元素的元组 (str前面, str, str后面)
string.rpartition(str)类似于 partition() 方法,不过是从右边开始查找
string.split(str="", num)以 str 为分隔符拆分 string,如果 num 有指定值,则仅分隔 num + 1 个子字符串,str 默认包含 ‘\r’, ‘\t’, ‘\n’ 和空格
string.splitlines()按照行(’\r’, ‘\n’, ‘\r\n’)分隔,返回一个包含各行作为元素的列表
string.join(seq)以 string 作为分隔符,将 seq 中所有的元素(的字符串表示)合并为一个新的字符串
字符串的切片

切片 方法适用于 字符串列表元组

  • 切片 使用 索引值 来限定范围,从一个大的 字符串切出 小的 字符串
  • 列表元组 都是 有序 的集合,都能够 通过索引值 获取到对应的数据
  • 字典 是一个 无序 的集合,是使用 键值对 保存数据
  • 字符串[开始索引:结束索引:步长]
    不包括结束位本身,左闭右开型。
  • 从头开始,开始索引数字可以省略,冒号不能省略
  • 到末尾结束,结束索引数字可以省略,冒号不能省略
  • 步长默认为1,如果连续切片,数字和冒号都可省略
    索引的顺序和倒序:
  • 在Python中不仅支持顺序索引,同时还支持倒序索引,
  • 所谓倒序索引就是从右向左计算索引,最右边索引值-1,依次递减,
  • 字符串的逆序str[::-1]
  • 字符串比较符合以下规则:“0”<“A”<“B”<“a”<“b”
  • str[::-2]从右到左,步长为2
运算符
  • [1, 2]+[3, 4] = [1, 2, 3, 4] 适用于字符串、列表、元组
  • [“hi”]*4=[“hi”,“hi”,“hi”,“hi”] 适用于字符串、列表、元组
  • < <= > >= == (1,2,3)<(2,2,3)返回True 适用于字符串、列表、元组
  • in 3 in (1,2,3) 返回True,适用于字符串、列表、元组、字典
  • not in 4 not in (1,2,3) 返回True
  • 注意,in在对字典操作时,判断的是字典的键
  • in not in被称作成员运算符
变量进阶
  • 引用:变量中记录数据的地址,就叫做引用
  • 在Python中,函数的实参和返回值都是靠引用来传递的
    可变类型和不可变类型:
  • 可变类型:内存中的数据可以被修改,如列表、字典
  • 不可变类型:内存中的数据不允许被修改,如数字类型、字符串、元组
  • 注意:可变类型的数据变化,是通过方法来实现的,如append(),即是通过方法修改变量内容,变量的引用不会改变
  • 如果给一个可变类型的变量,赋值了一个新的数据,引用会修改。
  • 在Python中,设置字典的键值对时,会首先对key进行hash以决定如何在内存中保存字典的数据,以方便后续对字典的增删改查
  • 在函数内部如果需要修改全局变量,需要使用global进行声明
  • 在Python中,可以将一个元组使用赋值语句同时赋给多个变量,如 a,b=b,a,其实(b,a)是一个元组
    面试题:交换两个数字
  • c=b,b=a, a=c
  • a=a+b,b=a-b,a=a-b
  • Python专用,利用元组:a,b=b,a
    面试题:"+="
  • 在Python中,列表变量调用"+="本质上是在执行列表变量的extend方法,不会修改变量的引用
  • 缺省参数,需要使用最常见的值作为默认值
  • 必须保证带有默认值的缺省参数在参数列表末尾,故这样定义是错误的def print_info(name,gender=True,age):
  • 调用带有多个缺省参数的函数,需要指定参数名,如def print_info(name,title="",gender=True)
  • 在调用时,print_info(“李四”, title=“班长”)
  • print_info(“张三”, gender=False)
    多值参数:
    *args–存放元组参数
    **kwargs–存放字典参数
    例如:
def demo(num, *args, **kwargs):
	pass
demo(1,2,3,4,5,name="李四",age=18,gender=True)
# 其中1是num,2,3,4,5是*args,其余为**kwargs	

元组和字典的拆包:

def demo(*args, **kwargs):
	gl_nums = (1, 2, 3)
	gl_list = {"name":"李四", "age":18}
	# 若用demo(gl_nums,gl_list),会把gl_nums和gl_list作为一个元组传递给*args.
	# 应该写成这样的格式:demo(*gl_num, **gl_kwargs),这就叫拆包
	

函数的递归:
在处理不确定的循环条件时,如遍历整个文件目录的结构,格外有用

  • 类名要求大驼峰命名法
  • 类名的确定:名词提炼法分析整个业务流程,出现的名词,通常就是找到的类
  • 使用内置函数dir传入标识符/数据,可以查看对象内的所有属性和方法
    __方法名__ 格式的方法是 Python 提供的 内置方法 / 属性
方法名作用
__new__创建对象时,会被 自动 调用
__init__对象被初始化时,会被 自动 调用
__del__对象被从内存中销毁前,会被 自动 调用
__str__返回对象的描述信息print 函数输出使用

Python定义一个类:

class 类名:
	def 方法1(self, 参数列表):
		pass
	def 方法2(self, 参数列表):
		pass
  • 方法的定义格式和之前学习过的函数几乎一样
  • 区别在于方法的第一个参数必须是self,
  • 类名的命名规则要符合大驼峰命名法
  • 创建对象:对象变量=类名()
  • %d可以以十进制输出数字
  • %x可以以十六进制输出数字
  • 使用self,由哪一个对象调用的方法,方法内的self就是哪一个对象的引用,如tom.eat(),eat方法中的self就是对象tom
  • 在封装类的方法内部,self就表示当前调用方法的对象自己
  • 调用方法时,程序员不需要传递self参数,即tom.eat()中不用写与形参self对应的实参
  • 在方法内部,可以通过self.访问对象的属性,也可以通过self.调用其他的数以同一类的方法
  • 在类的外部,通过对象名.访问对象的属性和方法
  • 在类封装的方法中,通过self.访问对象的属性和方法
初始化方法
  • 当使用类名()创建对象时,会自动执行以下操作:(即自动调用初始化方法)
  • 1:为对象在内存中分配空间–创建对象
  • 2:为对象的属性设置初始值–调用初始化方法__init()__
  • __init()__方法是专门用来定义一个类具有哪些属性的方法
  • __init()__方法内部使用self.属性名=属性的初始值,就可以给定义属性
  • 定义属性之后,再使用该类创建的对象都会拥有该属性
class Cat():
	def __init__(self, name):
		self.name = name
		# 注意,右边的name是方法中的形参name,左边的name是真正的属性
		
  • __del__方法:一个对象的__del__方法一旦被调用,执行完__del__方法体内的所有语句后描绘将对象从内存删除,生命周期结束
  • __str__方法:在Python中,使用print输出对象变量,默认情况下,会输出这个变量引用的对象是由哪一个类创建的对象,以及这个对象在内存中的地址(十六进制的地址)
  • 如果在开发中,希望使用print输出对象变量时,能够打印自定义的内容,就可以利用__str__这个内置方法了
  • 注意,__str__方法必须返回一个字符串,例如:
class Dog():
	def __str__(self):
		return "必须返回一个字符串"
# 当创建对象tom = Dog(),print(tom)是会调用__str__方法,执行__str__方法中的语句,输出"必须返回一个字符串"

  • 在对象方法内部,是可以直接访问对象属性的,属性一般都定义在__init()__方法中
  • 同一个类创建的多个对象之间,属性互不干扰
  • 身份运算符is is not
  • 身份运算符用于比较两个对象的内存地址是否一致–是否是对同一个对象的引用
  • 在Python中针对None比较时,建议使用is判断
  • x is y类似于id(x)==id(y)
  • is和==的区别:
  • is用于判断两个变量引用对象是否为同一个;
  • ==用于判断引用变量的值是否相等
私有属性和私有方法
  • 在实际开发中,对象的某些属性或者方法可能只希望在对象的内部被使用,而不希望在外部被访问到
  • 在定义属性或方法时,在属性名或者方法名前增加两个下划线,定义的就是私有属性和方法,如__age(),__secret(self):
  • 单例设计模式:目的是让类创建的对象,在系统中只有唯一的一个对象或者实例
  • 每一次执行类名()返回的对象,都是同一个对象,内存地址都是相同的
  • 单例设计模式应用场景:音乐播放对象,回收站对象,打印机对象
  • __new__方法:使用类名()创建对象时,Python的解释器首先会调用__new__方法为对象分配空间
  • __new__方法是一个由object基类提供的内置的静态方法,主要作用有两个:
  • (1)在内存中为对象分配空间
  • (2)返回对象的引用
  • Python解释器获得对象的引用后,将引用作为第一个参数,传递给__init__方法
  • 重写__new__方法的代码非常固定,一定要
  • return super().__new__(cls)
  • 否则Python的解释器得不到分配了空间的对象引用,就不会调用对象的初始化方法
  • 注意:__new__方法是一个静态方法,在调用时需要主动传递cls参数,其他方法是self参数,如__init__(self)
Python中的单例
  • 单例:让类创建的对象,在系统中只有唯一的一个实例
  • (1)定义一个类属性,初始值是None,用于记录单例对象的引用
  • (2)重写__new__方法
  • (3)如果类属性is None,调用父类方法分配空间,并在类属性中记录结果
  • (4)返回类属性中记录的对象引用,例如
class MusicPlayer(object):
	# 所有的类,如果没有继承父类,都要写上最顶层的父类,基类object
	instance = None
	# 定义类属性记录单例对象引用
	def __new__(cls, *args, **kwargs):
		# 判断类属性是否已经被赋值
		if cls.instance is None:
			cls.instance = super().__new__(cls)
		return cls.instance
		

单例模式下实现只执行一次初始化工作:

  • 在每次使用类名()创建对象时,Python的解释器都会自动调用两个方法:__new____init__
  • 在上边对__new__方法改造之后,每次都会得到第一次被创建对象的引用,但是,初始化方法还会被再次调用
  • 需求:让初始化动作只被执行一次
  • 解决方法:
  • (1)定义一个类属性init_flag标记是否执行过初始化动作,初始值为False
  • (2)在__init__方法中,判断init_flag,如果为False就执行初始化动作
  • (3)然后将init_flag设置为True
  • (4)这样,创建新对象调用__init__方法时,初始化动作就不会被再次执行了,例如
class MusicPlayer(object):
	# 记录第一个被创建对象的引用
	instance = None
	init_flag = False
	def __new__(cls, *args, **kwargs):
		# 判断类属性是否为空对象
		if cls.instance is None:
			# 调用父类的方法,为第一个对象分配空间
			cls.instance = super().__new__(cls)
		return cls.instance
	def __init__(self):
		if not MusicPlayer.init_flag:
			print("初始化音乐播放器")
			MusicPlayer.init_flag = True
	# 创建多个对象
player1 = MusicPlayer()
player2 = MusicPlayer()
	# 只会输出一遍"初始化音乐播放器"

多态

未完待续…

  • 5
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值