背景

也许是我的脑容量不足放下太多东西,间接性不使用语言,大脑对语言基础细节的召回困难,需要短期从冷却的记忆中唤回与更新。

从开始接触计算机起,遇到的计算机语言一个接一个,每四年熟练一门语言到放弃一门语言,从计算机语言发展史及 AI 的发展,让我们隐隐约约的感知到:以后的编程语言趋近于自然语言,从目前个人的眼光看,计算机语言还能再抽象出一门和自然语言更接近的语言出来,我们觉得 Python、PHP 等动态语言很适合接近自然语言的,java、golang 偏向于工程语言,前者在工程、性能上赶不上后者,后者适合专业团队,不适合个人。一直有个想法,以后人人是开发者,门槛越来越低,意味着编程语言的门槛也要低,个人可能不会去关心对象和接口,语言编写输入会去掉更多的约束规范,趋近于自然语言,通过一种 IDE 可以准确严谨地裁剪接收输入,执行代码,得到约定的规范的结果,这种 IDE 可能内含了面向对象或面向接口的思想,但并不暴露给个人。个体将会有更高级的任务与工作范式,计算机编程不再是一项高级且复杂的任务。

推荐一本书奇思妙想,从书中,我们可以了解计算机与编程语言的一些有趣的发展史;

推荐一个课程:【40 级全 中文字幕 计算机科学速成课】【Crash Course Computer Science】,我们最喜欢课程里的小课堂,每次小课堂都是计算机编程语言或思想的一次抽象与升级,从过去的发展来看,预测未来还会有更多趋近于自然语言的高级语言出现。

变量

  • 常用数据类型:int、float、str、bool(True、False)。
  • 私有变量:name
  • 受保护变量:name
  • type 函数取得变量类型:type(a)。
  • 转换数据类型:int()\float()\str()\bool() 。
  • int(c,base=2) 支持指定进制。

运算符

  • 幂:**
  • 整除://
  • 身份运算符:isis not
  • 成员运算符:innot in
  • 逻辑运算符:andornot
  • 赋值运算符:=+=-=*=/=%=**=//=&=|=^=>>=<<=
  • 海象运算符::=。用于条件或循环表达式中。if(n:=len(my_list))>10:print(n)
  • 不等于比较运算:!=

print

  • 输出:print()
  • 格式化:print('%s,%s'%(a,b))print('{0},{1}'.format(a,b))print(f'{a},{b}')
  • 新的格式化:
    • print(f'{a:>10}')
    • print(f'{a:^10}')
    • print(f'{a:<10}')
    • print(f'{a:10}')
    • print(f'{a:10.2f}')
    • print(f'{a:10.2f} {b:10.2f} {c:10.2f}')
    • 完整解释:<表示左对齐,^表示居中,>表示右对齐,10表示宽度,.2f表示小数点后两位。

分支结构

  • if、elif、else。
  • if 条件:
  • elif 条件:
  • else:
  • match case 实现多分支结构。python 3.10 新增。
  • match case 自动终止匹配,不需要显示的使用 break 关键字。

循环结构

  • for-in 循环。
    • for i in range(10):print(i)
    • 列表:for i in [1,2,3,4,5]:print(i)
    • 元组:for i in (1,2,3,4,5):print(i)
    • 字典:for i in {'a':1,'b':2,'c':3}:print(i)
    • 字符串:for i in 'abcde':print(i)
    • 集合:for i in {1,2,3,4,5}:print(i)
    • 迭代器:for i in iter([1,2,3,4,5]):print(i)
  • range 函数:range(start,stop,step)。step 表示步长。
  • while 循环。相当于 for if 循环。
  • break 和 continue。只支持跳出最近的循环,不支持直接跳出多层循环。

数据结构之列表

  • 列表:列表是由一系元素按特定顺序构成的数据序列。
  • 类型:list。
  • 字面量语法:[1,2,3,4,5]
  • 特点:允许重复、允许嵌套、允许混合数据类型。一般建议同一类型存储。
  • 列表运算
    • 拼接:a+b。类似于字符串的拼接。
    • 重复运算:a*b。类似于字符串的重复运算。
    • 索引:a[i]。索引从 0 开始。支持负数:-1 表示最后一个元素,-2 表示倒数第二个元素。
    • 成员运算::innot in。范例:if i in a:print(i)
    • 列表遍历:[i for i in range(10)]
  • 列表切片
    • 切片运算:a[start:stop:step]。切片是左闭右开,即不包含右侧的索引元素。
    • 切片与列表的关系,存在引用关系。其中切片是浅拷贝,即修改切片中的元素,也会修改原列表中的元素。
  • 列表方法
    • 列表在底层是一个对象,所以其会有自己的方法。
    • 添加元素:追加append()、指定索引添加insert()
    • 删除元素:删除指定索引元素del、删除指定元素remove()、删除所有指定元素pop()、删除所有元素clear()
    • 列表排序:sort()reverse()
    • 列表复制:copy()
    • 元素位置与频次:index()count()

元组

  • 元组:元组是由一系元素按特定顺序构成的数据序列,元组与列表不同的是元组不允许修改。属于不可变类型。
  • 类型:tuple。
  • 字面量语法:(1,2,3,4,5)
  • 特点:不可变。
  • 元组打包::a=1,2,3,创建了一个元组 a,其中有 3 个元素。
  • 元组解包:i,j,k=a,将元组中的元素分别赋值给 3 个变量。注意:元素个数与变量个数要对上。
  • 交换变量值:a,b=b,a。也支持 3 个:a,b,c=c,a,b。是由 python 字节码指令直接支持 2、3 个变量交换。
  • 元素与列表的比较
    • 使用场景:列表的元素是可变类型,元组的元素是不可变类型。不可变适合于多线程环境。
    • 不可变类型创建效率高于可变类型。

字符串

  • 字面量语法:'abcde'"abcde"'''abcde'''"""abcde"""

  • 类型:str。本质可以理解为字符的元组。

  • 转义字符:同其他语言。

  • 支持 16 进制、Unicode 字符编码:\x\u。如:\x41\u0041,分别表示字符:A、A。

  • 字符串运算

    • 拼接:a+b
    • 重复:a*b
    • 比较运算:a>ba<ba>=ba<=ba==ba!=b。比较的本质是比较字符串的 ASCII 码值。A<a,因为 ASCII 码值:A=65、a=97。
    • 索引:a[i]。索引从 0 开始。支持负数:-1 表示最后一个元素,-2 表示倒数第二个元素。
    • 切片:a[start:stop:step]
    • 成员运算::innot in。范例:'a' in 'apple'
  • 字符串方法

    • 字符串也有自己的方法。
    • 字符串长度:len()
    • 大写:upper()
    • 单词首字母大写:title()
    • 小写:lower()
    • 查找:find()rfind()index()rindex()
    • 性质判断:isalpha()isdigit()isspace()islower()isupper()istitle()isprintable()endswith()startswith()等。
    • 格式化:center()ljust()rjust()zfill()strip()lstrip()rstrip()format()
    • 修剪与替换:strip()lstrip()rstrip()replace()
    • 拆分与合并:split()rsplit()join()。join 方法比较特殊:'#'.join(a),用#号连接迭代对象 a 的字符串元素。
    • 编码与解码:encode()decode()。范例:a.encode('utf-8')
  • 字符串是不可变类型。所以对字符串的改变或是通过字符串方法改变字符串内容,本质是重新创建了个新的字符串,原来的字符串并没有改变,且还存在,直到引用计数为 0 才被回收。

集合

  • 集合:集合是由一系元素按特定顺序构成的数据序列,集合不允许重复。
  • 字面量语法:{1,2,3,4,5}set([1,2,3,4,5])set('abcde')
  • 类型:set。可变类型。
  • 集合元组必须是 hashabe 类型,即能够计算出稳定的海马的数据类型,也就是不可变类型才可以作为集合的元素。
  • 空集合:set()。不能用 {} 表示空集合,这个表示空字典。
  • 集合元素遍历:for i in a:print(i)
  • 集合运算
    • 成员运算::innot in
    • 交集、并集、差集、对称差集:a&ba|ba-bb-aa^b(交集取反)。
  • 子集和超集判断:a.issubset(b)a.issuperset(b)
  • 交集判断:a.isdisjoint(b)
  • 集合方法
    • 添加、删除、清空元素:add()remove()clear()
    • 集合长度:len()
  • 不可变集合:frozenset()。与 set 的区别在于不能增删修改修改。

字典

  • 字典:字典是由一系键值对构成的数据序列,字典不允许重复。
  • 字面量语法:{1:'a',2:'b',3:'c'}
  • 类型:dict。可变类型。
  • 字典方法
    • 字典获取:get()keys()values()items()会将键值对封装成元组。
    • 字典合并:update(),比如:a.update(b)。也可以通过或运算:a|b
    • 字典删除:pop()指定 key 删除、popitem()指定 key 删除并反馈键值对二元组、clear()清空留下空字典、del

函数

  • 重复是最坏的一种代码坏味道。
  • 字面量语法:def func1(a,b):return a+b
  • 入参
    • 位置参数范例:func1(1,2)
    • 默认参数范例:func1(a=1,b=2)。注意:带默认参数的参数,必须放在没有默认参数的参数后面。
    • 关键字参数范例:func1(b=2,a=1)。可用于不按顺序入参的情况。
    • 强制位置参数函数定义范例:def func1(a,b,/):return a+b。参数列表中用``/`,表示强制位置参数。
    • 命名关键字参数函数定义范例:def func1(*,a,b):return a+b。参数列表中用*,表示命名关键字参数。
    • 可变参数:def func1(*args):return args。参数列表中用*,表示可变参数,元组类型。使用范例:func1(1,2,3,4,5)。可变参数入参列表/元组/集合范例:func1(*[1,2,3,4,5]),称为解包。
    • 可变关键字参数:def func1(**kwargs):return kwargs。参数列表中用**,表示可变关键字参数,字典类型。使用范例:func1(a=1,b=2,c=3,d=4,e=5)
    • 可变参数与可变关键字参数可以同时在函数入参中存在。函数签名范例:def func1(a,b,*args,**kwargs):return a+b
  • 出参
    • 指定出参类型函数定义范例:def func1(a,b)->int:return a+b->int表示返回值类型为 int。
    • 可变出参函数定义范例:`def func1(a,b)

函数进阶

  • 一等函数:指的是函数可以赋值给变量,可以作为参数传递给函数,可以作为函数的返回值。
  • 内置高阶函数:map()filter()reduce()sorted()等,都支持了内部操作的函数抽象,允许外部传入一个具体的函数给高阶函数调用执行。
  • map函数是实现序列中元素映射的函数。
  • filter函数是实现对序列中元素的过滤
  • reduce函数是对序列中元素进行聚合的函数。
  • Lambda 函数:lambda函数,匿名函数,只能一行代码,lambda函数的参数和返回值由:分隔。范例:lambda x:x+1。是不是有点像海象运算符的效果。
  • 偏函数:是指固定函数的某些参数,生成一个新的函数。
  • 偏函数范例:int2=functools.partial(int,base=2),生成了 int2 函数,用于指定二进制的转换。
  • 装饰器:用一个函数装饰另一个函数并为其提供额外能力。
  • 装饰器本质:将入参函数传入,经过装饰器函数内包装后,返回一个包装后的新的函数,即在原函数执行前后补充额外逻辑代码。def decorator(func):def wrapper(*args,**kwargs):return func(*args,**kwargs)return wrapper
  • 装饰器语法糖:@decorator

模块

  • 模块:用于解决命名冲突问题。
  • 模块定义:一个文件代表一个模块。
  • 关键字:importfromas
  • 范例:
    • 导入一个模块:import module1
    • 导入一个模块中的一个方法函数:from module1 import func1
    • 导入一个模块的一个方法函数并重新命名:from module1 import func1 as f1
  • 内置函数不需要导入,直接使用。

面向对象

  • 定义类 class:class Student:

  • 创建对象:obj=Student()

  • 输出对象内存地址:print(id(obj)),再转换成十六进制:print(hex(id(obj)))

  • 初始化方法:__init__(self,name,age)

  • 面向对象的访问权限:___,分别表示:私有受保护

  • 假设__name 是私有属性,但仍然可以通过这方式访问:obj._Student__name。只是为了字面上提醒,不要直接使用。

  • 支柱仍然是封装继承多态。

  • 动态属性:obj.nick='张三'。python 允许动态添加类属性。

  • 静态方法:@staticmethod

    @staticmethod
    def func1(a):
        print(a)
    
  • 类方法:@classmethod。静态方法和类方法是发送给类的消息,本质上没有区别。

    @classmethod
    def func1(cls,a):
        print(a)
    
  • 继承:class Student(Person):

  • super 函数:是 Python 内置函数中专门为获取当前对象的父类对象而设计的。范例:super().__init__(name,age)

  • 简单的总结对象方法、类方法、静态方法。都可以通过“类名。方法名”的方式来调用,区别在于方法的第一个参数到底是普通对象还是类对象,还是没有接受消息的对象。静态方法通常也可以直接写成一个独立的函数,因为它并没有跟特定的对象绑定


9ong@TsingChan 2025 markdown