python 知识1
python里面所有的东西都是对象
- assert
# 断言
a = 1
assert a>0 , "error"
关键字,assert用来确保某个条件必须为真,如果为真,则顺利执行,如果为假,则抛出AssertionError错误,并且打印后面的字符串。
- 深拷贝和浅拷贝
浅拷贝:当改了原来的数据 新的数据也会变(两者本质上是一个数据)
# 直接赋值和copy.copy都是 浅拷贝
import copy
original = [[1, 2, 3], [4, 5, 6]]
new2 = copy.copy(original)
new = original
original[0][0] = 100
print(new) # 输出 [[100, 2, 3], [4, 5, 6]]
print(new2) # 输出 [[100, 2, 3], [4, 5, 6]]
深拷贝:成为了新的数据结构 和原来的数据结构无关(是两个数据结构了)
# copy.deepcopy是深拷贝
import copy
original = [[1, 2, 3], [4, 5, 6]]
new3 = copy.deepcopy(original)
original[0][0] = 100
print(original) # 输出 [[100, 2, 3], [4, 5, 6]]
print(new3) # 输出 [[1, 2, 3], [4, 5, 6]]
- sorted排序
直接对列表排序
# 直接对列表进行排序
A = [2, 4, 3, 5, 1]
sorted_A = sorted(A)
print(sorted_A) # 输出 [1, 2, 3, 4, 5]
对字典进行排序
# 根据 字典值进行排序
dict_A = {"A": 1, "B": 5, "C":2, "D": 4, "E": 3}
sorted_A = dict(sorted(dict_A.items(), key=lambda x: x[1]))
print(sorted_A) # 输出 {'A': 1, 'C': 2, 'E': 3, 'D': 4, 'B': 5}
使用规则进行排序
1 按照字符串长短进行排序
# 根据字符串长度进行排序
strings = ["C", "C++", "python", "java", "git"]
sorted_A = sorted(strings, key=lambda x: len(x))
print(sorted_A) # ['C', 'C++', 'git', 'java', 'python']
2 多个条件进行排序
# 根据age进行排序
data = [
{'name': 'A', 'age': 20},
{'name': 'B', 'age': 10},
{'name': 'C', 'age': 13},
{'name': 'D', 'age': 30}
]
sorted_A = sorted(data, key=lambda x: x['age'])
print(sorted_A) # [{'name': 'B', 'age': 10}, {'name': 'C', 'age': 13}, {'name': 'A', 'age': 20}, {'name': 'D', 'age': 30}]
# 根据字符串里面的内容进行排序
data = [
"filename01.txt", "filename06.txt", "filename10.txt", "filename09.txt", "filename07.txt"
]
sorted_A = sorted(data, key=lambda x: x.split(.)[0][-2:])
print(sorted_A) # ['filename01.txt', 'filename06.txt', 'filename07.txt', 'filename09.txt', 'filename10.txt']
- python命名规则
单_开头的变量是内部使用,被视为私有的,例如
class A():
def __init__(self):
self._name = "wayne"
# self._name属性应该只能在内部访问
两个_开头的变量会触发命名改写机制,是私有的,例如
class A():
def __init__(self):
self.__name = "wayne"
# 类名.__name 无法访问到
obj = A()
print(obj.__name) # 出现AttributeError错误
print(obj._A__name) # 可以访问 但不建议
个_变量的变量是避免和python的关键字相同。例如
class A():
pass
# class是用来命名类的 关键字
class_ = 10 # class_ 用来表示变量
- python中魔法方法
使用双_开头和双_结尾的属性或者方法是python官方自定义的,有特出含义的,开发者要避免使用
__init__(self,····) # 构造函数
__call__() # 让实例对象像函数一样调用
__str__() # 对象的字符串表示
__len__() # 返回对象的长度
# 一个类中如果有 __str__方法
# 当print这个类的实例对象时,会打印出这个方法的内容
# 在对象中加入参数,会直接调用__call__方法,像使用函数一样进行调用
- python中的迭代器和可迭代对象
可迭代对象意为可以迭代的对象,列表,字典,元组,字符串都是可迭代对象。
from collections.abc import Iterable
from collections.abc import Iterator
print(isinstance([11, 22, 33], Iterable)) # True
print(isinstance((11, 22, 33), Iterable)) # True
print(isinstance("112233", Iterable)) # True
print(isinstance(100, Iterable)) # False
- 判断一个对象能不能使用
for循环遍历,看其是否在内部实现了__iter__()方法,如果实现了则isinstance(abc, Iterable)返回为True - 如果一个对象同时实现了
__iter()__和__next__()方法那么就是一个迭代器 __iter()__的返回值是一个迭代器的引用- 使用
iter(对象实例)和next(对象示例)方法可以调用该类中中__iter()__和__next__()方法
迭代器一定是可迭代对象,可迭代对象不一定是迭代器(重点)
迭代器一个重要应用是,保存数据的生成方式,而不是保存数据本身
# 斐波那契数列
class Feibonaci():
def __init__(self, count):
self.count = count
self.num = list()
self.a = 0
self.b = 1
self.current = 0
def __iter__(self):
# 直接返回自己的引用
return self
def __next__(self):
if self.current < self.count:
ret = self.a
# 斐波那契数据的生成方式
self.a, self.b = self.b, self.a+self.b
self.current += 1
return ret
else:
# 告知for循环 元素已经取完
raise StopIteration
feibonaci = Feibonaci(10)
for temp in feibonaci:
print(temp)
- 生成器
生成器是特殊的迭代器,使用关键字yield来声明。当一个函数内部使用yield关键字,那么就是一个生成器,其存在意义是暂存程序的运行
# 使用生成器来完成斐波那契数列
def feibonaqi(nums):
a, b = 0, 1
current = 0
while current < nums:
ret = a
# print(ret)
yield ret
a, b = b, a+b
current +=1
obj = feibonaqi(10)
for temp in obj:
print(temp)
使用next(对象示例)程序会一直执行到yield关键字停止程序,然后保存程序状态,再次使用next(对象示例)会再次执行到yield关键字停止程序,保存程序......
将列表推导式的[]改为()就会改为生成器,例如
A = [i*2 for i in range(10)]
print(A) # [0, 2, 4, 6, 8, 10, 12, 14, 16, 18]
B = (i*2 for i in range(10)) # 生成器不能直接打印出来
print(B) # <generator object <genexpr> at 0x000002DD23531F50>
for j in B:
print(j)
- lambda表达式
也被称为匿名表达式,本质上是函数,但少了函数名称。语法格式为lambda 参数: 表达式,也可以嵌套lambda,返回值是一个对象。下面是常用的例子,
当使用函数的功能时需要在函数名字后面加(),将函数作为参数传入,不需要加。
f = lambda : "你好"
print(f()) # lambda无参数 结果----你好
f = lambda x, y : x+y
print(f(1, 2)) # 结果 3
# 嵌套 lambda
f = lambda x : lambda y : x+y
f2 = f(1) # 结果是一个lambda 表达式
print(f2(2)) # 结果为3
- python中可变参数
对python中的参数,进行解释
*args在函数内部为一个元组类型,里面为要传入的参数的值,可变位置参数**keyargs在函数内部为一个字典类型,里面为参数名称=参数值,可变关键字参数- 在函数定义中,参数的定义顺序很重要。顺序是位置参数、关键字参数、可变位置参数、可变关键字参数
- 使用可变关键字参数,可以模拟重载的效果。
- 可变参数实际上是个解包的过程
def test1(a, b=2, *args):
print("a的值: ", a)
print("b的值: ", b)
for i in args:
print(i)
test1(1) # 结果 a=1 b=2
test1(1, 3, 4, 5, 6, 7) # 结果 a=1 b=2 剩余参数在args里
# 关键字参数
def test2(a=1, b=2):
print("a的值: ", a)
print("b的值: ", b)
test2(8, 9) # a=8, b=9
test2(a=8, b=9) # a=8, b=9
# 可变关键字参数
def test3(a, b=2, **keyargs):
print("a的值: ", a)
print("b的值: ", b)
for key, value in keyargs.items():
print(key, value)
test3(1, 3, c=8, d=9) # a=1 b=3 c=8 d=9
# 混合参数 参数顺序很重要
def test1(a, b=2, *args, **keyargs):
print("a的值: ", a)
print("b的值: ", b)
print("可变位置参数为: ", args)
for key, value in keyargs.items():
print(key, value)
test1(1, 3, 4, 5, 6, name="wayne", sex="male") #
- 解包
将一个可迭代对象分解出来的过程称为解包,其中,可变位置参数,可变关键字参数也是用了类似的解包原理。
# 使用可迭代对象进行解包
a, b , c = [1, 2, 3] # 自动解包
print(a, b, c) # 结果 1 2 3
# 在函数传递参数可以使用 * 来解包
A = [4, 5, 6]
def add(a, b, c):
return a+b+c
print(add(*A)) # 15
# 字典类型的数据可以使用 ** 来进行解包
B = {"name":"wayne", "age": "24"}
def persosn(name, age):
return (f"name: {name}, age:{age}")
print(persosn(**B)) # name: wayne, age:24
# 相当于传入参数 name="wayne",age="24"
实际上对函数的参数可以传入一个列表或者字典(都是可迭代对象)来进行传递参数