文章目录
加载目录中...

python基础知识(1)

管理员 2025-09-05 23:58 54 阅读 python

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"

实际上对函数的参数可以传入一个列表或者字典(都是可迭代对象)来进行传递参数