Back
Featured image of post Python - 基础

Python - 基础

Python 计算

数字

# 加减乘除
print(2 + 2)	# 4
print(4 - 3)	# 1
print(6 * 2)   # 12
print(17 / 3)	# 5.666667

# 去掉小数点
print(17 // 3) # 5

# 取模运算
print(17 % 3)	# 2

# 幂运算
print(3 ** 2)	# 9
# 变量赋值
tax = 12.5 / 100
price = 100.50
print(price * price)

文本

# 打印字符串
print("Hello")	# Hello

# 转义
print("I\'m")	# I'm
print(r'C:\user\local') # C:\user\local

# 打印多行
print("""\
	Man,
	what can I said.
""")

# 字符拼接
print(2*"O" + "k")	# OOK

列表

# 打印列表
squares = [1, 4, 9]
print(squares)	# [1, 4, 9]

# 索引切片
squares[0]	# 1
squares[-1] # 9
squares[-2:] # [4, 9]

# 相同引用
rgb = ["Red", "Green", "Blue"]
rgba = rgb
print(id(rgb) == id(rgba))	# True

# 清空列表
squares[:] = []
print(squares) # []

Python 流程控制

分支结构

# if 语句
x = intput("请输入一个数字:")
if x < 0:
    print("x是负数!")
elif x == 0:
    print("x是零!")
else:
    print("x是正数!")

循环结构

# for 循环
animals = ['cat', 'panda', 'elephant']
for a in animals:
    print(a, len(a))
    
# 迭代集合副本
weeks = {'Mon':1, 'Tue':2, 'Wen':3}
for d, n in weeks.copy().items():
    print(d, n)

其他语句

# range()函数
for i in range(4):
    print(i)	# 0 1 2 3 
    
print(list(range(3, 5)))	# 3 4

print(list(range(0, 10, 3)))	# 0 3 6 9

print(sum(range(4)))	# 6
# break 和 continue
for n in range(2, 10):
    for x in range(2, n):
        if n % x == 0:
            print(n, '相当于', x, '*', n//x)
            break
        else:
            print(n, '是质数')
        
for num in range(2, 10):
    if num % 2 == 0:
        print("偶数 ", num)
        continue
    print("奇数 ", num)
# pass 什么也不执行
while True:
    pass
# match	"_" 为通配符 一定会执行
def http_error(status):
    match status:
        case 400:
            return "Bad request"
        case 401|403:
            return "Not allowed"
        case 404:
            return "Not found"
        case 418:
            return "I'm a teapot"
        case _:		
            return "Something's wrong with the internet"

Python 函数

函数定义

def fib(n):
    a, b = 0, 1
    while a < n:
        print(a, end=' ')
        a, b = b, a + b
    print()
    
def ask_ok(prompt, retries=4, reminder='Please try again!'):
    while True:
        reply = input(prompt)
        if reply in {'y', 'ye', 'yes'}:
            return True
        if reply in {'n', 'no', 'nop', 'nope'}:
            return False
        retries = retries - 1
        if retries < 0:
            raise ValueError('invalid user response')
        print(reminder)

函数参数

# *name 接收元组  **name 接收字典
def fun(*argument, **keywords):
    for arg in argument:
        print(arg)
    print("-------")
    for kw in kewords:
        print(kw, ":", keywords[kw])
        
# / 限制前面的参数只能按位置传递
# * 限制后面的参数只能按关键字传递
def combined_example(pos_only, /, standard, *, kwd_only):
    print(pos_only, standard, kwd_only)
print(combined_example(1, 2, kwd_only=3))

# 任意参数列表
def concat(*args, sep="/")
	return sep.join(args)
print(concat("earth", "mars", "venus"))	# 'earth/mars/venus'

# * 将实参从列表或元组解包
args = [3, 6]
print(list(range(*args)))

Lambda表达式

# 匿名函数写法
def make_incrementor(n):
    return lambda x: x + n;
f = make_incrementor(3)
print(f(1))		# 4
print(f(2))		# 6

# 匿名函数作实参
paris = [(1, 'one'), (2, 'two'), (3, 'three'), (4, 'four')]
paris.sort(key=lambda pair:pair[1])
print(paris)

函数注解

# -> 用来指示函数返回类型	
# __annotations__ 是函数的注解
def f(ham: str, eggs: str = 'eggs') -> str:
    print("Annotations:", f.__annotations__)
    print("Arguments:", ham, eggs)
    return ham + ' and ' + eggs

高阶函数

map()函数接收两个参数,一个是函数,一个是Iterablemap将传入的函数依次作用到序列的每个元素,并把结果作为新的Iterator返回。

r = map(lambda x: x*x, [1, 2, 3, 4])

print(list(r))

reduce把一个函数作用在一个序列[x1, x2, x3, ...]上,这个函数必须接收两个参数,reduce把结果继续和序列的下一个元素做累积计算。

from functools import reduce

i = reduce(lambda x, y: 10*x + y, [j for j in range(10) if j % 2 != 0])

print(i)

filter()也接收一个函数和一个序列。和map()不同的是,filter()把传入的函数依次作用于每个元素,然后根据返回值是True还是False决定保留还是丢弃该元素。

def is_odd(n):
    return n % 2 == 1

print(list(filter(is_odd, [1, 2, 4, 5, 6, 9, 10, 15])))

yield用法。

def g(n):
    while n > 0:
        yield n
        n = n - 1
print(g(10))

Python 数据结构

列表

# 定义列表
animals = ['cat', 'dog', 'donkey', 'panda', 'elephant', 'panda']

# count() 计数
print(animals.count('panda'))	# 2

# index() 索引
print(animals.index('elephant'))	# 4

# reverse() 反转
print(animals.reverse())	# ['panda','elephant', 'panda', 'donkey', 'dog', 'cat']

# append() 添加
print(animals.append('pig'))	# ['cat','dog', 'donkey', 'panda', 'elephant', 'panda', 'pig']

# sort() 排序
animals.sort()
print(animals)	# ['cat','dog', 'donkey', 'panda', 'elephant', 'panda', 'pig']

# pop() 弹出
print(animals.pop)	# pig
# 列表实现栈
stack = [3, 4, 5]

# 入栈
stack.append(6)

# 出栈
stack.pop()
# 列表实现队列
from collections import deque
queue = deque(["Mike", "John", "Tim"])

# 入队
queue.append("Terry")

# 出队
queue.popleft()

元组和序列

# 元组由多个逗号隔开的值组成
tuples = 123, 4455, 'python'
print(t)	# (123, 455, 'python')

t = ([1,2,3], [3,2,1])
print(t)	# ([1,2,3], [3,2,1])

集合

# 创建集合用 {} 或 set()
basket = {'apple', 'orange', 'apple'}
print(basket)	# {'orange', 'banana', 'pear', 'apple'}

a = set('abracadabra')
b = set('alacazam')

print(a - b)	# 'r', 'd', 'b'
print(a | b)	# 'a', 'c', 'r', 'd', 'b', 'm', 'z', 'l'
print(a & b)	# 'a', 'c'
print(a ^ b)	# 'r', 'd', 'b', 'm', 'z', 'l'

字典

# 字典是键值对
tel = {'jack': 4098, 'sape': 4139}
t = dict([('sape', 4139), ('guido', 4127), ('jack', 4098)])

# 删除
del tel['jack']

# 添加
tel['irv'] = 4127

# 判断
print('guido' in del)	# True

循环技巧

# items() 提取键值对
knights = {'gallahad': 'the pure', 'robin': 'the brave'}
for k, v in knights.items():
    print(k, v)
    
# enumerate() 提取索引和值
for i, v in enumerate(['tic', 'tac', 'toe']):
    print(i, v)

# zip() 循环多个序列
questions = ['name', 'quest', 'favorite color']
answers = ['lancelot', 'the holy grail', 'blue']
for q, a in zip(questions, answers):
    print('What is your {0}?  It is {1}.'.format(q, a))
    
# reversed() 逆向
for i in reversed(range(1, 10, 2)):
    print(i)
    
# sorted() 排序
basket = ['apple', 'orange', 'apple', 'pear', 'orange', 'banana']
for i in sorted(basket):
    print(i)

Python IO编程

由于CPU和内存的速度远远高于外设的速度,所以,在IO编程中,就存在速度严重不匹配的问题。同步和异步的区别就在于是否等待IO执行的结果。

文件读写

# 以读文件模式打开一个文件对象
f = open("/Users/local/test.txt", 'r')

# 一次读取文件全部内容
f.read()

# 关闭文件
f.close()

# 用 with 自动关闭文件和处理异常
# f.readline():读取单行数据保留换行符
# f.readline():返回空字符串表示到文件末尾
# f.tell():返回文件对象在文件中的位置
# f.seek(offset, whence):可改变文件对象位置
with open('/Users/local/test.txt', 'r', encoding='gbk') as f:
    for line in f.readlines():
        print(line.strip())	# 去掉换行符
        
with open('/Users/local/test.txt', 'w', encoding='gbk') as f:
    f.write('Hello, World!')

内存读写

# StringIO 将字符串写入内存
from io import StringIO
f = StringIO()
f.write("Hello")
print(f.getvalue())

# BytesIO 将字节写入内存
from io import BytesIO
f = BytesIO()
f.write('中文'.encode('utf-8'))
print(f.getvalue())

文件和目录操作

# 导入 OS
import os

# 查看当前目录的绝对路径
os.path.abspath('.')

# 新目录完整路径表示
os.path.join('/Users/local', 'testdir')

# 创建目录
os.mkdir('/Users/local/testdir')

# 删除目录
os.rmdir('/Users/local/testdir')

# 文件路径拆分
os.path.split('/Users/local/testdir/file.txt')

# 获取文件拓展名
os.path.splitext('/Users/local/testdir/file.txt')

# 文件重命名
os.rename("file.txt", "file.py")

# 文件删除
os.remove("file.py")

# 列出当前目录下所有目录
[x for x in os.listdir('.') if os.path.isdir(x)]

# 列出所有 .py 文件
[x for x in os.listfir('.') if os.path.isfile(x) and os.paht.splitext(x)[1]='.py']

序列化

把变量从内存中变成可存储或传输的过程称之为序列化,在Python中叫pickling,在其他语言中也被称之为serialization,marshalling,flattening等等,都是一个意思。

反过来,把变量内容从序列化的对象重新读到内存里称之为反序列化,即unpickling。

# 将对象序列化为 bytes
import pickle
d = {'name':'Bob', 'age':20, 'score':88}
print(pickle.dumps(d))

# 将序列化的对象写入文件
with open('dump.txt', 'wb') as f:
    pickle.dump(d, f)
    
# 直接读取序列化对象
with open('dump.txt', 'rb') as f:
    print(pickle.load(f))
# JSON 格式
import json
d = {'name':'Bob', 'age':20, 'score':88}
print(json.dumps(d))

# 将序列化的对象写入文件
with open('dump.json', 'w') as f:
    json.dump(d, f)
    
# 直接读取序列化对象
with open('dump.json', 'r') as f:
    print(json.load(f))

# 类要转换为字典才能被序列化
print(json.dumps(s, default=lambda obj: obj.__dict__))

# 同理,反序列化也是一样的
print(json.loads(json_str, object_hook=dict2student))

字符串格式化

# 格式化字面值
year = 2024
name = 'Mike'
print(f'{name} love {year}')

# str.format() 方法 
yes_votes = 42_572_654
no_votes = 43_132_495
percentage = yes_votes / (yes_votes + no_votes)
print('{:-9} YES votes  {:2.2%}'.format(yes_votes, percentage))
print('{0}, {1}'.format(yes_votes, percentage))

Python 错误和异常

错误可(至少)被分为两种:语法错误 和 异常。

异常处理

# 单个值异常
while True:
    try:
        x = int(input("Please enter a number: "))
        break
    except ValueError:
        print("Oops!  That was no valid number.  Try again...")
# 多个异常处理
import sys

try:
    f = open('myfile.txt')
    s = f.readline()
    i = int(s.strip())
except OSError as err:
    print("OS error:", err)
except ValueError:
    print("Could not convert data to an integer.")
except Exception as err:
    print(f"Unexpected {err=}, {type(err)=}")
    raise
# else 子句
for arg in sys.argv[1:]:
    try:
        f = open(arg, 'r')
    except OSError:
        print('cannot open', arg)
    else:
        print(arg, 'has', len(f.readlines()), 'lines')
        f.close()

异常触发

# raise 强制触发异常
raise NameError('HiThere')

# 只想判断是否有异常但不处理
try:
    raise NameError('HiThere')
except NameError:
    print('An exception flew by!')
    raise

调用栈

如果错误没有被捕获,它就会一直往上抛,最后被 Python 解释器捕获,打印一个错误信息,然后程序退出。

# 可以记录错误信息
def foo(s):
    return 10 / int(s)

def bar(s):
    return foo(s) * 2

def main():
    try:
    	bar('0')
    except Exception as e:
        logging.exception(e)
    
main()    

调试

# assert 
def foo(s):
    n = int(s)
    # 如果 n !=0 就会抛出错误
    assert n != 0, 'n is zero!'
    return 10 / n

def main():
    foo('0')
# logging
# 级别:debug、info、warning、error
import logging
logging.basicConfig(level=logging.INFO)

s = '0'
n = int(s)
logging.info('n = %d' % n)
print(10 / n)

单元测试

单元测试是用来对一个模块、一个函数或一个类来进行正确性检验的测试工作。

# Dict类
class Dict(dict):
    def __init__(self, **kw):
        super().__init__(**kw)

    def __getattr__(self, key):
        try:
            return self[key]
        except KeyError:
            raise AttributeError(r"'Dict' object has no attribute '%s'" % key)

    def __setattr__(self, key, value):
        self[key] = value
# Dict测试
"""
	assertEqual(abs(-1), 1)	断言函数返回结果与1是否相等
	assertRaises(KeyError)	期待抛出指定类型异常
"""
import unittest
from mydict import Dict

class TestDict(unittest.TestCase):

    def test_init(self):
        d = Dict(a=1, b='test')
        self.assertEqual(d.a, 1)
        self.assertEqual(d.b, 'test')
        self.assertTrue(isinstance(d, dict))

    def test_key(self):
        d = Dict()
        d['key'] = 'value'
        self.assertEqual(d.key, 'value')

    def test_attr(self):
        d = Dict()
        d.key = 'value'
        self.assertTrue('key' in d)
        self.assertEqual(d['key'], 'value')

    def test_keyerror(self):
        d = Dict()
        with self.assertRaises(KeyError):
            value = d['empty']

    def test_attrerror(self):
        d = Dict()
        with self.assertRaises(AttributeError):
            value = d.empty
# setUP 与 tearDown 分别在测试方法调用前后执行
class TestDice(unittest.TestCase):
    def setUp(self):
        print('setUp..')
	
    def tearDown(self):
        print('tearDown..')

Python 面向对象编程

作用域和命名空间

"""
	nonlocal 会改变 scope_test 对 spam 的绑定
	global 会改变模块层级的绑定
"""
def scope_test():
    def do_local():
        spam = "local spam"

    def do_nonlocal():
        nonlocal spam
        spam = "nonlocal spam"

    def do_global():
        global spam
        spam = "global spam"

    spam = "test spam"
    do_local()
    print("After local assignment:", spam)
    do_nonlocal()
    print("After nonlocal assignment:", spam)
    do_global()
    print("After global assignment:", spam)

scope_test()
print("In global scope:", spam)

类基础

# 定义一个基础的类
class Dog:

    def __init__(self, name):
        # 在变量前 __ 就变成私有变量
        self.__name = name
        self.tricks = [] 

    def add_trick(self, trick):
        self.tricks.append(trick)

继承和多态

# 继承基类方法,多态覆盖基类方法
class Animal(object):
    def run(self):
        print('Animal is running...')
        
class Dog(Animal):
    def run(self):
        print('Dog is running...')

class Cat(Animal):
    pass

# 判断某个变量是否是某个类型
a = Animal()
d = Animal()
print(a, Animal) # True
print(d, Animal) # True

定制类

# __str__ 打印类实例
class Student:
    def __init__(self, name):
        self.name = name
    
    def __str__(self):
        return 'Student object (name: %s)' % self.name
    # __repr___ 直接显示变量调用信息
    __repr___ = __str___
print(Student("Tom"))
# __iter__ 获取一个迭代对象
class Fib:
    def __init___(self):
        self.a, self.b = 0, 1
        
    def __iter___(self):
    	return self
    
    def __next___(self):
		self.a, self.b = self.b, self.a + self.b
        if self.a > 100_100:
            raise StopIteration()
        return self.a
# __getitem__ 用下标取出元素
class Fib:
    def __getitem__(self, n):
        if isinstance(n, int)	# n 是索引的时候
            a, b = 1, 1
            for x in range(n):
                a, b = b, a + b
            return a
        if isinstance(n, slice)	# n 是切片
        	start = 0 if n.slice is None else n.slice
            stop = n.stop
			a, b = 1, 1
            L = []
            for x in range(stop):
                if x >= start:
                    L.append(a)
                a, b = b, a + b
            return L
# __getattr___ 动态返回一个属性
class Student:

    def __init__(self):
        self.name = 'Mike'

    def __getattr__(self, attr):
        if attr=='score':
            return 99
        elif attr=='age':
            return lambda: 25
# __call()__ 直接调用实例
class Student(object):
    def __init__(self, name):
        self.name = name

    def __call__(self):
        print('My name is %s.' % self.name)

# Callable 判断调用是对象还是函数
print(callable(Student()))
print(callable([1, 2, 3]))
Licensed under CC BY-NC-SA 4.0
Built with Hugo
Theme Stack designed by Jimmy
© Licensed Under CC BY-NC-SA 4.0