Python入门
基础
see: https://liaoxuefeng.com/books/python/introduction/index.html
- 运行速度慢
- 代码不能加密
输出
name = input()
name = input(); age = input(); print("name" , name , "age" , age)
数据类型和变量
- 整数 10000000000可以写为10_000_000_000
- 浮点数 1.23x10⁹ == 1.23e9
- 字符串
- 'I'm "OK"!' = I'm "OK"!
- \n表示换行,\t表示制表符
- Python允许用'''...'''的格式表示多行内容
>>> print('''line1 ... line2 ... line3''')
- 多行字符串'''...'''还可以在前面加上r使用
print(r'''hello,\n world''')
- 布尔值 True、False、not True
字符串
- %替换: %s表示用字符串替换,%d表示用整数替换
>>> 'Hello, %s' % 'world'
'Hello, world'
>>> 'Hi, %s, you have $%d.' % ('Michael', 1000000)
'Hi, Michael, you have $1000000.'
- %格式化整数和浮点数还可以指定是否补0和整数与小数的位数
print('%2d-%03d' % (3, 1)) # %2d会给3补1个空格,%02d会给1补2个0 print: 3-001
print('%.2f' % 3.1415926) # 保留两位小数 print:3.14
print('growth rate: %d %%' % 7) # 转移% 用两个%% print:growth rate: 7 %
- format 替换下标
>>> 'Hello, {0}, 成绩提升了 {1:.1f}%'.format('小明', 17.125)
'Hello, 小明, 成绩提升了 17.1%'
- f-string 替换变量
>>> r = 2.5
>>> s = 3.14 * r ** 2 # ** 2 平方
>>> print(f'The area of a circle with radius {r} is {s:.2f}')
The area of a circle with radius 2.5 is 19.62
编码
- ASCII编码,只存储大小写英文字母、数字和一些符号
- Unicode把所有语言都统一到一套编码里,这样就不会再有乱码问题了
- UTF-8编码 “可变长编码”,UTF-8编码把一个Unicode字符根据不同的数字大小编码成1-6个字节,节约空间
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
List有序集合
- 定义 classmates = ['Michael', 'Bob', 'Tracy']
- 插入
- classmates.append('Adam')
- classmates.insert(1, 'Jack')
- 删除 classmates.pop(1)
- 替换 classmates[1] = 'Sarah'
- tuple 不可变集合,定义 t = (1,) 或 t = (1, 2)
- 切片
- L[0:3] / L[:3] 从索引0开始取,直到索引3为止,但不包括索引3
- L[-2:-1] 倒数切片
- L[:10:2] 前10个数,每两个取一个
- L[::5] 所有数,每5个取一个
- L[:] 只写[:]就可以原样复制一个list
条件判断
- if: else:
- if: elif:
- 只要x是非零数值、非空字符串、非空list等,就判断为True,否则为False
- match语句
score = 'B'
match score:
case 'A':
print('score is A.')
case 'B':
print('score is B.')
case _: # _表示匹配到其他任何情况
print('score is ???.')
循环、遍历、迭代
- for x in []
- while
- break
- continue
- 判断是否可遍历 from collections.abc import Iterable \n isinstance('abc', Iterable)
- 下标遍历 for i, value in enumerate(['A', 'B', 'C']): \n print(i, value)
- 迭代器
- 集合对象都不是Iterator对象
- from collections.abc import Iterator \n isinstance([], Iterator) = False \n isinstance(iter([]), Iterator) = True
# 首先获得Iterator对象:
it = iter([1, 2, 3, 4, 5])
# 循环:
while True:
try:
x = next(it)
except StopIteration:
break # 遇到StopIteration就退出循环
dict(map)
- d = {'Michael': 95, 'Bob': 75, 'Tracy': 85} d['Michael'] = 95
- d.get('Thomas') = None d.get('Thomas', -1) = -1
- 删除 d.pop('Bob')
- 遍历key for key in d
- 遍历value for value in d.values()
- 都遍历 for k, v in d.items()
- **dict 字典解包操作符,用于将字典的键值对解包并传递给另一个字典。
set
- s = {1, 2, 3}
- 非重复,无序
- 新增 s.add(4)
- 删除 s.remove(4)
列表生成式(生成器)
- [x * x for x in range(1, 11)]
- [x * x for x in range(1, 11) if x % 2 == 0]
- [k + '=' + v for k, v in d.items()]
- [x if x % 2 == 0 else -x for x in range(1, 11)]
函数
- 类型转换 int('123') int(12.34)=12 str(1.23)='1.23' bool(1)=True bool('')=False
- 定义函数 def
- 空函数 def nop(): /n pass
- 参数检查 if not isinstance(x, (int, float)): /n raise TypeError('bad operand type')
- 返回多个值 x, y = move() def move(): return nx, ny 原理是返回的tuple(不可变集合)
- 默认参数 def power(x, n=2) 默认计算二次方,多个默认参数可以在调用的时候指定enroll('Adam', 'M', city='Tianjin'),注意默认参数必须指向不变对象!
- 可变参数 def calc(*number) 调用calc(*nums)把集合转换为可变参数
- 关键字参数 允许传入0个或任意个含参数名的参数 def person(name, age, **kw): person('Adam', 45, gender='M', job='Engineer'), **ky不会改变对象引用
- 命名关键字参数def person(name, age, *, city, job): 设定只能传递city和job传参数
- 参数组合,参数定义的顺序必须是:必选参数、默认参数、可变参数、命名关键字参数和关键字参数
- 递归函数,尾递归优化解决栈增长问题
函数式编程
传入函数
def add(x, y, f):
return f(x) + f(y)
add(-5, 6, abs) ==>
x = -5
y = 6
f = abs
f(x) + f(y) ==> abs(-5) + abs(6) ==> 11
return 11
高阶函数
map
map()函数接收两个参数,一个是函数,一个是Iterable,map将传入的函数依次作用到序列的每个元素,并把结果作为新的Iterator返回
def f(x):
return x * x
r = map(f, [1, 2, 3, 4, 5, 6, 7, 8, 9])
list(r) = [1, 4, 9, 16, 25, 36, 49, 64, 81]
reduce
reduce把一个函数作用在一个序列[x1, x2, x3, ...]上,这个函数必须接收两个参数,reduce把结果继续和序列的下一个元素做累积计算
reduce(f, [x1, x2, x3, x4]) = f(f(f(x1, x2), x3), x4)
from functools import reduce
def add(x, y):
return x + y
reduce(add, [1, 3, 5, 7, 9]) = 25
filter
filter()把传入的函数依次作用于每个元素,然后根据返回值是True还是False决定保留还是丢弃该元素。
def is_odd(n):
return n % 2 == 1
list(filter(is_odd, [1, 2, 4, 5, 6, 9, 10, 15])) = [1, 5, 9, 15]
sorted
sorted(['bob', 'about', 'Zoo', 'Credit'], key=str.lower, reverse=True)
匿名函数
list(map(lambda x: x * x, [1, 2, 3, 4, 5, 6, 7, 8, 9]))
# 等价
def f(x):
return x * x
装饰器
def log(func):
def wrapper(*args, **kw):
print('call %s():' % func.__name__)
return func(*args, **kw)
return wrapper
@log
def now():
print('2024-6-1')
偏函数
创建新函数
>>> import functools
>>> int2 = functools.partial(int, base=2)
>>> int2('1000000')
64
>>> int2('1010101')
85
使用模块
#!/usr/bin/env python3 # linux和mac下有效
# -*- coding: utf-8 -*- # 编码
' a test module ' # 注释
__author__ = 'Michael Liao' # 作者
# 直接调用的时候才会生效,引入不行,可用于测试
if __name__=='__main__':
test()
面向对象
类和实例
class Student(object):
def __init__(self, name, score):
self.name = name
self.score = score
def print_score(self):
print('%s: %s' % (self.name, self.score))
访问限制
属性名称增加__变为私有变量(private)
class Student(object):
def __init__(self, name, score):
self.__name = name
self.__score = score
def get_name(self):
return self.__name
def get_score(self):
return self.__score
def set_score(self, score):
self.__score = score
继承和多态
class Animal(object):
def run(self):
print('Animal is running...')
class Dog(Animal):
def run(self):
print('Dog is running...')
def eat(self):
print('Eating meat...')
b = Animal() # b是Animal类型
c = Dog() # c是Dog类型
isinstance(b, Animal) = True
isinstance(c, Dog) = True
动态语言
动态语言的“鸭子类型”,它并不要求严格的继承体系,一个对象只要“看起来像鸭子,走起路来像鸭子”,那它就可以被看做是鸭子
Python的“file-like object“就是一种鸭子类型。对真正的文件对象,它有一个read()方法,返回其内容。但是,许多对象,只要有read()方法,都被视为“file-like object“
对象信息判断
- type() 判断对象类型
- type(123)==int type('abc')==str
- type(fn)==types.FunctionType
- type(abs)==types.BuiltinFunctionType
- type(lambda x: x)==types.LambdaType
- type((x for x in range(10)))==types.GeneratorType
- isinstance() 判断class的类型
- isinstance(h, Husky) == True
- isinstance('a', str) == True
- isinstance(123, int) == True
- isinstance(b'a', bytes) == True
- isinstance([1, 2, 3], (list, tuple)) == True
- isinstance((1, 2, 3), (list, tuple)) == True
- dir() 获得一个对象的所有属性和方法
- hasattr(obj, 'x') # 有属性'x'吗?
- setattr(obj, 'y', 19) # 设置一个属性'y'
- getattr(obj, 'y') # 获取属性'y'
- getattr(obj, 'z', 404) # 获取属性'z',如果不存在,返回默认值404
使用@property
class Student(object):
@property
def birth(self):
return self._birth
@birth.setter
def birth(self, value):
self._birth = value
@property
def age(self):
return 2025 - self._birth
异常
基本
try:
print('try...')
r = 10 / int('a')
print('result:', r)
except ZeroDivisionError as e:
print('ZeroDivisionError:', e)
except Exception as e:
print('Exception:', e)
finally:
print('finally...')
print('END')
抛出错误
class FooError(ValueError):
pass
def foo(s):
n = int(s)
if n==0:
raise FooError('invalid value: %s' % s)
return 10 / n
foo('0')
# 向上抛出
try:
10 / 0
except ZeroDivisionError:
# raise 异常向上抛
raise ValueError('input error!') # 抛出为其他异常
断言
- assert n != 0, 'n is zero!' 如果断言失败,assert语句本身就会抛出AssertionError
- python -O err.py 统一关闭断言 大写O
正则
- 基本
>>> import re
>>> re.match(r'^\d{3}\-\d{3,8}$', '010-12345')
<_sre.SRE_Match object; span=(0, 9), match='010-12345'> # 成功返回match对象
>>> re.match(r'^\d{3}\-\d{3,8}$', '010 12345')
>>> # 失败返回None
- 切分字符串
re.split(r'\s+', 'a b c') = ['a', 'b', 'c']
re.split(r'[\s\,]+', 'a,b, c d') = ['a', 'b', 'c', 'd']
re.split(r'[\s\,\;]+', 'a,b;; c d') ['a', 'b', 'c', 'd']
- 分组
>>> m = re.match(r'^(\d{3})-(\d{3,8})$', '010-12345')
>>> m
<_sre.SRE_Match object; span=(0, 9), match='010-12345'>
>>> m.group(0)
'010-12345'
>>> m.group(1)
'010'
>>> m.group(2)
'12345'
- 编译
>>> import re
# 编译:
>>> re_telephone = re.compile(r'^(\d{3})-(\d{3,8})$')
# 使用:
>>> re_telephone.match('010-12345').groups()
('010', '12345')
>>> re_telephone.match('010-8086').groups()
('010', '8086')
文件读写
读
with open('/path/to/file', 'r') as f:
# print(f.read()) 读所有
for line in f.readlines():
print(line.strip()) # 把末尾的'\n'删掉
写
with open('/Users/michael/test.txt', 'w') as f: # a为追加
f.write('Hello, world!')