python笔记

基础语法

>>>

默认的python提示符,往往会显示于能以交互方式在解释器里执行的样例代码之前。

...

输入特殊代码时默认的 Python 提示符,特殊代码包括缩进的代码块,左右成对分隔符(圆括号、方括号、花括号或三重引号等)之内,或是在指定一个装饰器之后。

字面量

在代码中,被写下来的的固定的值,称之为字面量

注:type()语句可以查看变量存储的数据类型

注释

行注释:以 # 开头,直到该物理行结束。注释可以在行开头,或空白符与代码之后,但不能在字符串里面。字符串中的 # 号就是 # 号。
多行注释:以一对三个双引号引起来""" """

数据转换

语句(函数) 说明
int(x) 将x转换为一个整数
float(x) 将x转换为一个浮点数
str(x) 将对象 x 转换为字符串

python用作计算器

  • 解释器像一个简单的计算器:你可以输入一个表达式,它将给出结果值。 表达式语法很直观:运算符 +, -, * 和 / 可被用来执行算术运算;圆括号 (()) 可被用来进行分组。
>>>2 + 2
4
>>>50 - 5*6
20
>>>(50 - 5*6) / 4
5.0
>>>8 / 5  # 除法运算总是返回一个浮点数
1.6
  • 除法运算(/)总是返回浮点数。 如果要做 floor division (向下取整除法)得到一个整数结果你可以使用 // 运算符;要计算余数你可以使用%
  • Python 用 ** 运算符计算乘方:2 ** 7 #2的7次方
  • 如果变量未定义(即,未赋值),使用该变量会提示错误
  • Python 全面支持浮点数;混合类型运算数的运算会把整数转换为浮点数
  • 交互模式下,上次输出的表达式会赋给变量_。最好把该变量当作只读类型。不要为它显式赋值,否则会创建一个同名独立局部变量,该变量会用它的魔法行为屏蔽内置变量。
  • 复合赋值运算符:+= -= /= *= %= **= //=

字符串

  • 可以用成对的单引号('')或双引号("")标示
  • 要标示引号等特殊符号,需要用到转义字符,加一个\
  • 这两种引号唯一的区别是,不需要在单引号里转义双引号 " (但此时必须把单引号转义成 ' ),反之亦然
  • 如果不希望前置 \ 的字符转义成特殊字符,可以使用 原始字符串,在引号前添加 r 即可
    • print('C:\some\name')->print(r'C:\some\name')
    • 原始字符串还有一个微妙的限制:一个原始字符串不能以奇数个 \ 字符结束
  • 字符串文字可以跨越多行。一种方法是使用三重引号:"""..."""'''...''' 。行尾会自动包含在字符串中,但可以通过在行尾添加 \ 来避免这种情况。 在下面的示例中,不包含首行换行符
print("""\
Usage: thingy [OPTIONS]
     -h                        Display this usage message
     -H hostname               Hostname to connect to
""")
  • 字符串可以用+合并(粘到一起),也可以用*重复
  • 相邻的两个或多个 字符串字面值 (引号标注的字符)会自动合并。如'py''thon'->'python'
    • 拼接分隔开的长字符串时,这个功能特别实用
    • 不能用于变量或表达式
  • 字符串支持== 索引 ==(下标访问),第一个字符的索引是 0。单字符没有专用的类型,就是长度为一的字符串
    • 索引还支持负数,用负数索引时,从右边开始计数
    • 注意,-0 和 0 一样,因此,负数索引从 -1 开始。
  • 除了索引操作,还支持切片。 索引用来获取单个字符,而切片允许你获取子字符串
    • 例如:word[0:2] # 从 0 号位 (含) 到 2 号位 (不含) 的字符
    • 切片索引的默认值很有用;省略开始索引时,默认值为 0,省略结束索引时,默认为到字符串的结尾。如:`word[:2] word[4:]
    • 注意,输出结果包含切片开始,但不包含切片结束。因此,s[:i] + s[i:]总是等于s
    • 索引越界会报错,但是,切片会自动处理越界索引
    • Python 字符串不能修改,是 immutable 的。因此,为字符串中某个索引位置赋值会报错
  • 内置函数 len() 返回字符串的长度
    • s = 'supercalifragilisticexpialidocious' len(s)
字符串格式化

通过%占位符,完成字符串和变量的快速拼接(和c差不多)

格式化的精度控制
  • 可以使用辅助符号"m.n"来控制数据的宽度和精度
    • m,控制宽度,要求是数字,如果设置的宽度小于数字自身,则不生效
    • .n,控制小数点精度,要求是数字,会进行小数的四舍五入
字符串快速格式化

语法:f"内容{变量}"的格式来快速格式化
注:这种写法不做精度控制,不理会类型

数据输入

  • 使用input()语句可以从键盘获取输入
  • 注:无论键盘输入什么类型的数据,获取到的数据永远都是字符串类型,记得进行类型转换

多重赋值与循环体缩进

# 斐波那契数列:
# 前两项之和即下一项的值
a, b = 0, 1
#变量 a 和 b 同时获得新值 0 和 1 。
while a < 10:
    print(a)
    a, b = b, a+b
    #缩进是 Python 组织语句的方式。在交互式命令行里,得为每个缩进的行输入空格(或制表符)。使用文本编辑器可以实现更复杂的输入方式;所有像样的文本编辑器都支持自动缩进。交互式输入复合语句时,要在最后输入空白行表示完成(因为解析器不知道哪一行代码是代码块的最后一行)。注意,同一块语句的每一行的缩进相同。

i = 256*256
print('The value of i is', i)
The value of i is 65536

a, b = 0, 1
while a < 1000:
    print(a, end=',')#默认print语句输出内容会自动换行,关键字参数 end 可以取消输出后面的换行, 或用另一个字符串结尾
    a, b = b, a+b
0,1,1,2,3,5,8,13,21,34,55,89,144,233,377,610,987,

注:

  • print()输出的字符串不带引号
  • **- 的优先级更高, 所以 -3**2 会被解释成 -(3**2)

控制流工具

while语句

if语句

  • 归属于if判断的代码语句块,需在前方填充4个空格缩进
  • Python通过缩进判断代码块的归属关系。
x = int(input("Please enter an integer: "))

if x < 0:
    x = 0
    print('Negative changed to zero')
elif x == 0:
    print('Zero')
elif x == 1:
    print('Single')
else:
    print('More')

for语句

Python 的 for 语句与 C 或 Pascal 中的不同。Python 的 for 语句不迭代算术递增数值,或是给予用户定义迭代步骤和结束条件的能力(如 C),而是在列表或字符串等任意序列的元素上迭代,按它们在序列中出现的顺序

  • 例如
# 度量一些字符串:
words = ['cat', 'window', 'defenestrate']
for w in words:
    print(w, len(w))
  • for 循环遍历列表中的每个元素,将其赋值给变量 w。
  • w 是一个变量,它持有一个指向字符串对象的引用。(相当于指针)在循环中,w 的值(即它所指向的字符串对象)并没有被改变,而是 w 本身这个变量的引用被改变了,指向了列表中的下一个字符串对象。
  • 变量 w 只是改变了它所指向的内存地址,即指向了列表中的下一个字符串对象。这就是为什么尽管字符串是不可变的,w 的值(即它所指向的字符串)在循环中看起来像是被改变了,实际上只是 w 这个变量的引用在改变。
    很难正确地在迭代多项集的同时修改多项集的内容。更简单的方法是迭代多项集的副本或者创建新的多项集
  • 例如:
# 创建示例多项集
users = {'Hans': 'active', 'Éléonore': 'inactive', '景太郎': 'active'}

# 策略:迭代一个副本
for user, status in users.copy().items():
    if status == 'inactive':
        del users[user]

# 策略:创建一个新多项集
active_users = {}
for user, status in users.items():
    if status == 'active':
        active_users[user] = status

range()函数

  • 内置函数 range() 用于生成等差数列
  • 生成的序列绝不会包括给定的终止值;range(10) 生成 10 个值——长度为 10 的序列的所有合法索引。range 可以不从 0 开始,且可以按给定的步长递增(即使是负数步长)
for i in range(5):
    print(i)
0
1
2
3
4

list(range(5, 10))
[5, 6, 7, 8, 9]
list(range(0, 10, 3))
[0, 3, 6, 9]
list(range(-10, -100, -30))
[-10, -40, -70]
  • 要按索引迭代序列,可以组合使用 range() 和 len():
a = ['Mary', 'had', 'a', 'little', 'lamb']
for i in range(len(a)):
    print(i, a[i])
  • 也可以使用enumerate()函数
    • enumerate() 返回的迭代器的 next() 方法返回一个元组,里面包含一个计数值(从 start 开始,默认为 0)和通过迭代 iterable 获得的值。
seasons = ['Spring', 'Summer', 'Fall', 'Winter']
list(enumerate(seasons))
[(0, 'Spring'), (1, 'Summer'), (2, 'Fall'), (3, 'Winter')]
list(enumerate(seasons, start=1))
[(1, 'Spring'), (2, 'Summer'), (3, 'Fall'), (4, 'Winter')]
  • range() 返回的对象在很多方面和列表的行为一样,但其实它和列表不一样。该对象只有在被迭代时才一个一个地返回所期望的列表项,并没有真正生成过一个含有全部项的列表,从而节省了空间
  • 这种对象称为可迭代对象 iterable,适合作为需要获取一系列值的函数或程序构件的参数。for 语句就是这样的程序构件;以可迭代对象作为参数的函数例如 sum()如sum(range(10))

break 和 continue 语句

  • break 语句将跳出最近的一层 for 或 while 循环
  • continue 语句将继续执行循环的下一次迭代

循环的 else 子句

  • 在 for 或 while 循环中 break 语句可能对应一个 else 子句。 如果循环在未执行 break 的情况下结束,else 子句将会执行。
  • 在 for 循环中,else 子句会在循环结束其他最后一次迭代之后,即未执行 break 的情况下被执行。
  • 在 while 循环中,它会在循环条件变为假值后执行。
  • 在这两类循环中,当在循环被 break 终结时 else 子句 不会 被执行。 当然,其他提前结束循环的方式,如 return 或是引发异常,也会跳过 else 子句的执行。
for n in range(2, 10):
    for x in range(2, n):
        if n % x == 0:
            print(n, 'equals', x, '*', n//x)
            break
    else:
        # 循环到底未找到一个因数
        print(n, 'is a prime number')

pass语句

#pass 语句不执行任何动作。语法上需要一个语句,但程序毋需执行任何动作时,可以使用该语句
while True:
    pass  # 无限等待键盘中断 (Ctrl+C)

#常用于创建一个最小的类
class MyEmptyClass:
    pass

#pass 还可用作函数或条件语句体的占位符,让你保持在更抽象的层次进行思考。pass 会被默默地忽略
def initlog(*args):
    pass   # 记得实现这个!

match语句

match 语句接受一个表达式并把它的值与一个或多个 case 块给出的一系列模式进行比较。这表面上像 C、Java 或 JavaScript(以及许多其他程序设计语言)中的 switch 语句,但其实它更像 Rust 或 Haskell 中的模式匹配。只有第一个匹配的模式会被执行,并且它还可以提取值的组成部分(序列的元素或对象的属性)赋给变量。

  • 最简单的形式是将一个主语值与一个或多个字面值进行比较
def http_error(status):
    match status:
        case 400:
            return "Bad request"
        case 404:
            return "Not found"
        case 418:
            return "I'm a teapot"
        case _:
            return "Something's wrong with the internet"
  • 注意最后一个代码块:“变量名”_被作为 通配符 并必定会匹配成功。如果没有 case 匹配成功,则不会执行任何分支。
  • 可以用 | (“或”)将多个字面值组合到一个模式中
case 401 | 403 | 404:
    return "Not allowed"

函数

函数的定义:

def 函数名(传入参数)
    函数体
    return 返回值

注:如果函数没有使用return语句返回数据,会返回None这个字面量;在if判断中,None等同于False;定义变量,但暂时不需要变量有具体值,可以用None来代替

  • 使用 global关键字 可以在函数内部声明变量为全局变量

python数据容器

一种可以容纳多份数据的数据类型,容纳的每一份数据称之为1个元素。 每一个元素,可以是任意类型的数据

list(列表)

  • Python 支持多种复合数据类型,可将不同值组合在一起。最常用的列表是用方括号标注,逗号分隔的一组值。列表可以包含不同类型的元素,但一般情况下,各个元素的类型相同
  • 列表还支持合并操作
  • 列表是 mutable 类型,其内容可以改变,容纳上限2**63-1
  • Python 中的简单赋值绝不会复制数据。 当你将一个列表赋值给一个变量时,该变量将引用现有的列表。你通过一个变量对列表所做的任何更改都会被引用它的所有其他变量看到。
使用方式 作用
list.append(元素) 向列表的尾部追加一个元素
list.extend(容器) 向数据容器的内容(无结构)依次取出,追加到列表尾部
list.insert(下标、元素) 在指定下标处,插入指定的元素
del list[下标] 删除列表指定下标元素
list.pop(下标) 删除列表指定下标元素(能得到返回值)
list.remove(元素) 从前向后,删除此元素第一个匹配项
list.clear() 清空列表
list.count(元素) 统计此元素在列表中出现的次数
list.index(元素) 查找指定元素在列表的下标,找不到报错ValueError
len(列表) 统计容器内有多少元素

例如:

# 字面量
[元素1,元素2,...]

# 定义变量
squares(变量名称) = [1, 4, 9, 16, 25]
squares
[1, 4, 9, 16, 25]

# 定义空列表
变量名称 = []
变量名称 = list()

squares + [36, 49, 64, 81, 100]
[1, 4, 9, 16, 25, 36, 49, 64, 81, 100]

sqares.append(216)
sqares
[1,4,9,16,25,216]

rgb = ["Red", "Green", "Blue"]
rgba = rgb
id(rgb) == id(rgba)  # 它们指向同一个对象
  • 切片操作返回包含请求元素的新列表。以下切片操作会返回列表的浅拷贝
correct_rgba = rgba[:]
correct_rgba[-1] = "Alpha"
correct_rgba
["Red", "Green", "Blue", "Alpha"]
rgba
["Red", "Green", "Blue", "Alph"]
  • 为切片赋值可以改变列表大小,甚至清空整个列表
letters = ['a', 'b', 'c', 'd', 'e', 'f', 'g']
letters
['a', 'b', 'c', 'd', 'e', 'f', 'g']
# 替换一些值
letters[2:5] = ['C', 'D', 'E']
letters
['a', 'b', 'C', 'D', 'E', 'f', 'g']
# 现在移除它们
letters[2:5] = []
letters
['a', 'b', 'f', 'g']
# 通过用一个空列表替代所有元素来清空列表
letters[:] = []
letters
[]
* 为切片赋值可以改变列表大小,甚至清空整个列表
  • 内置函数 len() 也支持列表
  • 可以嵌套列表(创建包含其他列表的列表)
a = ['a', 'b', 'c']
n = [1, 2, 3]
x = [a, n]
x
[['a', 'b', 'c'], [1, 2, 3]]
x[0]
['a', 'b', 'c']
x[0][1]
'b'
浅层复制与深层复制(还没搞懂)
  • 浅层复制:构造一个新的复合对象,然后(在尽可能的范围内)将原始对象中找到的对象的引用 插入其中
  • 深层复制:构造一个新的复合对象,然后,递归地将在原始对象里找到的对象的副本插入其中

tuple(元组)

  • 基本语法:
# 定义元组字面量
(元素,元素,.......,元素)
# 定义元组变量
变量名称 = (元素,元素,.......,元素)
# 定义空元组
变量名称 = ()
变量名称 = tuple()
# 定义一个元素的元组:注意:此时必须带有逗号,否则不是元组类型
x = ('Hello', )
  • 元组的方法:
方法 作用
index() 查找某个数据,如果数据存在返回对应的下标,否则报错
count() 统计某个数据在当前元组出现的次数
len(元组) 统计元组内元素个数
  • 元组特点
# 不可以修改元组内容,否则会报错
t1 = (1,2,3)
t1[0] = 5
#可以修改元组内list的内容(修改元素、增加、删除、反转等)
t1 = (1,2,['ijia','asda'])
t1[2][1] = 'best'

字符串

  • 字符串容器可以容纳的类型是单一的,只能是字符串类型
  • 字符串不可以修改,如果必须要修改,只能得到一个新的字符串,旧的字符串是无法修改
  • 字符串的方法
操作 说明
str[] 根据下标索引取出特定位置字符
str.index(str) 查找给定字符的第一个匹配项的下标
str.replace(str1,str2) 将字符串内的全部字符串1,替换为字符串2。不会修改原字符串,而是得到一个新的
str.split(str) 按照给定字符串,对字符串进行分隔。不会修改原字符串,而是得到一个新的列表
str.strip() 或 str.strip(str) 移除首尾的空格和换行符或指定字符串
str.count(str) 统计字符串内某字符串的出现次数
len(str) 统计字符串的字符个数

序列的切片

  • 序列是指:内容连续、有序,可使用下标索引的一类数据容器
  • 列表、元组、字符串,均可以可以视为序列
  • 语法:序列[起始下标:结束下标:步长]
    • 表示从序列中,从指定位置开始,依次取出元素,到指定位置结束,得到一个新序列
    • 起始下标表示从何处开始,可以留空,留空视作从头开始
    • 结束下标(不含)表示何处结束,可以留空,留空视作截取到结尾
    • 步长表示,依次取元素的间隔
    • 步长为负数表示,反向取(注意,起始下标和结束下标也要反向标记)
  • 上面的列表有展示

set(集合)

  • 语法:
# 定义集合字面量
{element,element,......,element}
# 定义集合变量
变量名称 = {element,element,......,element}
# 定义空集合
变量名称 = set()
  • 集合的方法
操作 说明
set.add(element) 集合内添加一个元素
set.remove(element) 移除集合内指定的元素
set.pop() 从集合中随机删除一个元素并返回
set.clear() 将集合清空
set1.difference(set2) 得到一个新集合,内含2个集合的差集,原有的2个集合内容不变
set.difference_update(set2) 在集合1中,删除集合2中存在的元素,集合1被修改,集合2不变
set1.union(set2) 得到1个新集合,内含2个集合的全部元素,原有的2个集合内容不变
len(set) 得到一个整数,记录了集合的元素数量
  • 集合特点:相较于列表、元组、字符串来说,不支持元素的重复(自带去重功能)、并且内容无序

dict(字典)

  • 语法:
# 定义字典字面量
{key:value, key:value, ...... ,key:value}
# 定义字典变量
my_dict = {key:value, key:value, ...... ,key:value}
# 定义空字典
my_dict = {}
my_dict = dict()
  • 字典的方法
操作 说明
dict[key] 获取指定Key对应的Value值
dict[key] = value 添加或更新键值对
dict.pop(key) 取出Key对应的Value并在字典内删除此Key的键值对
dict.clear() 清空字典
dict.keys() 获取字典的全部Key,可用于for循环遍历字典
len(dict) 计算字典内的元素数量
  • 字典特点
    • 键值对的Key和Value可以是任意类型(Key不可为字典)
    • 字典内Key不允许重复,重复添加等同于覆盖原有数据
    • 字典不可用下标索引,而是通过Key检索Value

数据容器的通用操作

列表 元组 字符串 集合 字典
元素数量 支持多个 支持多个 支持多个 支持多个 支持多个
元素类型 任意 任意 仅字符 任意 Key:Value
Key:除字典外任意类型
Value:任意类型
下标索引 支持 支持 支持 不支持 不支持
重复元素 支持 支持 支持 不支持 不支持
可修改性 支持 不支持 不支持 支持 支持
数据有序
使用场景 可修改、可重复的一批数据记录场景 不可修改、可重复的一批数据记录场景 一串字符的记录场景 不可重复的数据记录场景 以Key检索Value的数据记录场景

容器通用功能:

功能 描述
通用for循环 遍历容器(字典是遍历key)
max() 容器内最大元素
min() 容器内最小元素
len() 容器元素个数
list() 转换为列表
tuple() 转换为元组
str() 转换为字符串
set() 转换为集合
sorted(序列,[reverse=Ture]) 排序,reverse=True表示降序
得到一个排好序的列表

函数进阶

函数多返回值

def test_return():
    return 1,2

x, y = test_return()
print(x)  print(y)
# 按照返回值的顺序,写对应顺序的多个变量接收即可 变量之间用逗号隔开

函数多种传参方式

位置参数

调用时根据函数定义的参数位置传参,传递的参数与定义的参数顺序和个数必须一致

def user_info(name,age,gender):
    print(f'您的名字是{name},年龄是{age},性别是{gender}')

user_info('Tom',20,'男')
关键字参数

函数调用时通过“键=值”形式传递参数

def user_info(name,age,gender):
    print(f'您的名字是{name},年龄是{age},性别是{gender}')

# 关键字传参:可以不按照固定顺序
user_info(age=20,gender='男',name='Tom')
# 可以和位置参数混用,位置参数必须在前,且匹配参数顺序
user_info('小明',age=20,gender='男')
缺省参数
  • 缺省参数也叫默认参数,用于定义函数,为参数提供默认值,调用函数时可不传该默认参数的值
  • 函数调用时,如果为缺省参数传值则修改默认参数值, 否则使用这个默认值
    注:所有位置参数必须出现在默认参数前,包括函数定义和调用
def user_info(name,age,gender='男'):
    print(f'您的名字是{name},年龄是{age},性别是{gender}')

uesr_info('Tom',20)
uner_info('Tom',18,'女')
不定长参数

不定长参数也叫可变参数. 用于不确定调用的时候会传递多少个参数(不传参也可以)的场景
不定长参数的类型:
1、位置传递

def user_info(*args)
    print(args)
# 传进的所有参数都会被args变量收集,它会根据传进参数的位置合并为一个元组(tuple),args是元组类型,这就是位置传递
user_info('Tom')# ('Tom',)
user_info('Tom',18)# ('Tom',18)

2、关键字传递

def user_info(**args)
    print(args)
# 参数是“键=值”形式的形式的情况下, 所有的“键=值”都会被kwargs接受, 同时会根据“键=值”组成字典
user_info(name='Tom',age=18,id=110)# {'name':'Tom','age':18,'id':110}

匿名函数

  • 函数的定义中
    • def关键字,可以定义带有名称的函数
    • lambda关键字,可以定义匿名函数(无名称)
      • 语法:`lambda 传入参数:函数体(一行代码)
      • 传入参数表示匿名函数的形式参数,如lambda x,y:...表示接收两个形式参数
      • 函数体是函数的执行逻辑,只能写一行,无法写多行
  • 有名称的函数,可以基于名称重复使用。 无名称的匿名函数,只可临时使用一次
    使用示例:
def test(com)
    re=com(1,2)
    print(re)
test(lambda x,y:x+y)

python文件操作

文件读取

mode常用的三种基础访问模式:

模式 描述
r 以只读方式打开文件。文件的指针将会放在文件的开头。这是默认模式。
w 打开一个文件只用于写入。如果该文件已存在则打开文件,并从开头开始编辑,原有内容会被删除。如果该文件不存在,创建新文件。
a 打开一个文件用于追加。如果该文件已存在,新的内容将会被写入到已有内容之后。如果该文件不存在,创建新文件进行写入。
操作 功能
文件对象 = open(file, mode, encoding) 打开文件获得文件对象
文件对象.read(num) 读取指定长度字节。不指定num读取文件全部
文件对象.readline() 读取一行
文件对象.readlines() 读取全部行,得到列表
for line in 文件对象 for循环文件行,一次循环得到一行数据
文件对象.close() 关闭文件对象
with open() as f 通过with open语法打开文件,可以自动关闭

文件写入

# 打开文件
f = open('python.txt','w')
# 文件写入
f.wirte('Hello World')
# 内容刷新
f.flush
  • 直接调用write,内容并未真正写入文件,而是会积攒在程序的内存中,称之为缓冲区
  • 当调用flush的时候,内容会真正写入文件
  • 这样做会频繁的操作硬盘,导致效率下降

python异常、模块与包

异常的捕获

在可能发生异常的地方,进行捕获。当异常出现的时候,提供解决方式,而不是任由其导致程序无法运行。

try:
    可能要发生异常的语句
except[异常 as 别名:]
    出现异常的准备手段
[else:]
    未出现异常应做的事
[finally:]
    不管出不出现异常都会做的事
# 异常的种类多种多样,如果想要不管什么类型的异常都能捕获到,那么使用:except Exception as e:

python模块

模块(Module),是一个 Python 文件,以 .py 结尾. 模块能定义函数,类和变量,模块里也能包含可执行的代码
模块的导入方式:

[from 模块名] import [模块 | 类 | 变量 | 函数 | *] [as 别名]

常用的组合形式如:

  • import 模块名
  • from 模块名 import 类、变量、方法等
  • from 模块名 import *
  • import 模块名 as 别名
  • from 模块名 import 功能名 as 别名
    每个Python文件都可以作为一个模块,模块的名字就是文件的名字
    在实际开发中,当一个开发人员编写完一个模块后,为了让模块能够在项目中达到想要的效果, 这个开发人员会自行在py文件中添加一些测试信息,但是在模块导入的时候都会自动执行test函数的调用
  • 解决方案:
def test(a,b)
    print(a+b)
# 只在当前文件调用该函数,其他导入的文件不符合该条件,则不执行test函数
if __name__ == '__main__':
    test(1,1)
  • 如果一个模块文件中有__all__变量,当使用from xxx import *导入时,只能导入这个列表中的元素
__all__ = ['test_A']
def test_A():
    print('A')
def test_B():
    print('B')
# 只能传输test_A函数

python包

从物理上看,包就是一个文件夹,在该文件夹下自动创建了一个 _ init _.py 文件,该文件夹可用于包含多个模块文件 从逻辑上看,包的本质依然是模块
~
当我们的模块文件越来越多时,包可以帮助我们管理这些模块, 包的作用就是包含多个模块,但包的本质依然是模块
导入包:
1.import 包名.模块名 调用:包名.模块名.目标
2.from 包名 import * 必须在__init__.py文件中添加__all__ = [],控制允许导入的模块列表

面向对象

成员方法

  • 在Python中,如果将函数定义为class(类)的成员,那么函数会称之为:方法
# 函数
def add(x,y):
    return x+y
# 方法
class Student:
    def add(self,x,y):
        return x+y
  • self关键字 ,它是成员方法定义的时候,必须填写的,但是传参的时候可以忽略它
    • 它用来表示类对象自身的意思
    • 当我们使用类对象调用方法的是,self会自动被python传入
    • 在方法内部,想要访问类的成员变量,必须使用self
  • 方法和函数功能一样, 有传入参数,有返回值,只是方法的使用格式不同:
# 函数的使用
num = add(1,2)
# 方法的使用
student = Student()
num = student.add(1,2)

构造方法

  • 基于类创建对象的语法:对象名 = 类名称()
  • python类可以使用:__init__()方法,称之为构造方法
  • 在创建类对象(构造类)的时候,会自动执行,并将传入参数自动传递给__init__方法使用
class student:
    name = None
    age = None
    tel = None
def __init__(self,name,age,tel):
    self.name = name
    self.age = age
    self.tel = tel
    print("Student类创造了一个对象")
stu = student("Tom",31,16554665460)

封装

  • 面向对象编程,是基于模板(类)去创建实体(对象),使用对象完成功能开发
  • 面向对象包含3大主要特性:封装 继承 多态
  • 将现实世界事物在类中描述为属性和方法,即为封装
  • 现实事物有部分属性和行为是不公开对使用者开放的。同样在类中描述属性和方法的时候也需要达到这个要求,就需要定义私有成员了
    • 成员变量和成员方法的命名均以__作为开头即可
class phone:
    i=None
    p=None
    __curr = None  # 私有成员变量
    def __keep(...):  # 私有成员方法
        ...
# 私有成员无法被类对象使用,但可以被其他成员使用
    def call(self)
        if self.__curr>=1:
            self.__keep()

继承

  • 将从父类那里继承(复制)来成员变量和成员方法(不含私有)
    • 单继承
    • 多继承
      • 多个父类中,如果有同名的成员,那么默认以继承顺序(从左到右)为优先级
      • pass是占位语句,用来保证函数(方法)或类定义的完整性,表示无内容,空的意思
    • 复写:子类继承父类的成员属性和成员方法后,如果对其“不满意”,那么可以进行复写。即在子类中重新定义同名的属性或方法即可
      • 一旦复写父类成员,那么类对象调用成员的时候,就会调用复写后的新成员 如果需要使用被复写的父类的成员,需要特殊的调用方式:

多态

  • 指的是完成某个行为时,使用不同的对象会得到不同的状态,多态常作用在继承关系上
  • 抽象类(接口):含有抽象方法的类称之为抽象类
  • 抽象方法:方法体是空实现的(pass)称之为抽象方法
  • 抽象类多用于做顶层设计(设计标准),以便子类做具体实现,要求子类必须复写(实现)父类的一些方法
posted @ 2024-11-26 08:18  micryfotctf  阅读(8)  评论(0编辑  收藏  举报