Python基础回顾

xiaoxiao2021-02-28  16

数字,字符串和变量

Python里的所有数据——布尔值,整数,浮点数,字符串,甚至大型数据结构,函数以及程序都是以对象(object)的形式存在 对象的类型决定了它装着的数据是允许被修改的变量(可变的)还是不可被修改的常量(不可变的)。你可以把不可变对象想象成一个透明但封闭的盒子:你可以看到里面装的数据,但是无法改变它。类似地,可变对象就像一个开着口的盒子, 你不仅可以看到里面的数据,还可以拿出来修改它,但你无法改变这个盒子本身,即你无法改变对象的类型 Python中的变量有一个非常重要的性质:它仅仅是一个名字。赋值操作并不会实际复制值,它只是为数据对象取个相关的名字。名字是对对象的引用而不是对象本身。你可以把名字想象成贴在盒子上的标签

数字

分浮点数除法和整数除法

>>> 7 / 2 3.5 >>> 7 // 2 3

函数divmod()同时得到商和余数(元组形式)

>>> divmod(7,2) (3, 1)

进制 1. 二进制 0b or 0B 2. 八进制 0o or 0O 3. 十六进制 0x or 0X

int类型可存储任意大小的整数

>>> 10 ** 100 10000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000

Python在处理超大数计算方面不会产生任何错误

函数float()可转换任何有效浮点值

>>> float('1.0e4') 10000.0

字符串

可用单引号,双引号,三引号创建字符串(主要用于创建多行字符串)

函数print()会在各个部分之间添加空格

>>> print(1, 'haha', 'hehe') 1 haha hehe

拼接字符串的两种方式 1. 使用+拼接

>>> 'first' + 'second' 'firstsecond'

2. 字符串紧接着放置

>>> 'first' 'second' 'firstsecond'

使用*号复制字符串

>>> 'abc' * 3 'abcabcabc'

使用[ ]提取字符(偏移量不能超过字符串长度)

>>> s = 'abcdefg' >>> s[0] 'a' >>> s[2] 'c' >>> s[-1] 'g'

一些常用字符串函数

>>> s = 'get gloves,get mask, give cat vitamins' >>> s.split(',') ['get gloves', 'get mask', ' give cat vitamins'] >>> ','.join(s.split(',')) 'get gloves,get mask, give cat vitamins' >>> s.startswith('get') True >>> s.endswith('ins') True >>> s.find('glo') 4 >>> s.rfind('glo') 4 >>> s.count('g') 4 >>> s.isalnum() False >>> s.capitalize() 'Get gloves,get mask, give cat vitamins' >>> s.title() 'Get Gloves,Get Mask, Give Cat Vitamins' >>> s.upper() 'GET GLOVES,GET MASK, GIVE CAT VITAMINS' >>> s.lower() 'get gloves,get mask, give cat vitamins' >>> s.center(40) ' get gloves,get mask, give cat vitamins ' >>> s.ljust(40) 'get gloves,get mask, give cat vitamins ' >>> s.replace('give', 'get') 'get gloves,get mask, get cat vitamins' >>> s.replace('g', 'G', 10) 'Get Gloves,Get mask, Give cat vitamins'

列表,元组,字典与集合

列表

使用 [offset]获取与修改元素

>>> ls = ['a', 'b', 'c', 'd'] >>> ls[0] 'a' >>> ls[-2] 'c' >>> ls[1] = 'g' >>> ls ['a', 'g', 'c', 'd']

使用extend()或+=合并列表

>>> a = [1, 2, 3] >>> b = [4, 5, 6] >>> c = [7, 8, 9] >>> a.extend(b) >>> a [1, 2, 3, 4, 5, 6] >>> b += c >>> b [4, 5, 6, 7, 8, 9]

使用sort()重新排列元素

列表方法sort()会改变原列表内容函数sorted()返回排好序的列表副本

>>> ls = [1, 3, 5, 4, 2] >>> sorted(ls) [1, 2, 3, 4, 5] >>> ls [1, 3, 5, 4, 2] >>> ls.sort() >>> ls [1, 2, 3, 4, 5]

一些常用列表函数

>>> ls = [1, 2, 3, 'a', 'b', 'c'] >>> ls.insert(2, 4) >>> ls [1, 2, 4, 3, 'a', 'b', 'c'] >>> del ls[3] >>> ls [1, 2, 4, 'a', 'b', 'c'] >>> del ls[-1] >>> ls [1, 2, 4, 'a', 'b'] >>> ls.remove('a') >>> ls [1, 2, 4, 'b'] >>> ls.pop() 'b' >>> ls [1, 2, 4] >>> ls.pop(2) 4 >>> ls [1, 2] >>> ls.index(2) 1 >>> ls.count(1) 1

元组

创建只含一个元素的元组时,元素后需加逗号,元素数大于1时最后元素后面的逗号可省略

>>> t = ('a',) >>> type(t) <class 'tuple'> >>> t2 = ('a') >>> type(t2) <class 'str'> >>> t3 = 'a', >>> type(t3) <class 'tuple'> >>> t4 = 'a', 'b' >>> type(t4) <class 'tuple'>

元组解包以及多变量互换

>>> t = (1, 2, 3) >>> x, y, z = t >>> x 1 >>> y 2 >>> z 3 >>> v = 'a' >>> v2 = 'b' >>> v, v2 = v2, v >>> v 'b' >>> v2 'a'

字典

Python3.6字典默认有序(以后的版本不保证有序)

>>> d = {'a' : 'b', 'c' : 'd', 'e' : 'f'} >>> for i in d: ... print(i) ... a c e >>> for i in d: ... print(i) ... a c e >>> for i in d: ... print(i) ... a c e

使用dict()将包含双值子序列的序列转换成字典

>>> ls = [['a', 'b'], ['c', 'd']] >>> dict(ls) {'a': 'b', 'c': 'd'} >>> t = ('ab', 'cd') >>> dict(t) {'a': 'b', 'c': 'd'}

使用update()合并字典(若重复,新值取代旧值)

>>> d = {1:2, 3:4} >>> d2 = {1:5, 6:7} >>> d.update(d2) >>> d {1: 5, 3: 4, 6: 7}

使用del与clear()删除元素

>>> d = {'a':'b', 'c':'d', 'e':'f'} >>> del d['a'] >>> d {'c': 'd', 'e': 'f'} >>> d.clear() >>> d {}

集合

使用{ }创建集合

>>> s = {1, 2, 3, 4} >>> type(s) <class 'set'>

将字符串转换为集合

>>> set(str) {'e', 'a', 'c', 'd', 'b'}

常用集合运算

>>> a = {1, 2} >>> b = {2, 3} >>> a & b {2} >>> a | b {1, 2, 3} >>> a - b {1} >>> b - a {3} >>> a ^ b {1, 3} >>> a <= b False >>> a <= a True >>> a < b False >>> a < a False

代码结构

风格和规范

使用 \ 连接代码

>>> 1 + 2 + File "<stdin>", line 1 1 + 2 + ^ SyntaxError: invalid syntax >>> 1 + 2 + \ ... 3 6

连续比较

>>> x = 7 >>> 6 < x < 10 < 999 True >>> 6 < x > 3 True

假值表

类型值布尔Falsenull类型None整形0浮点型0.0空字符串’ ‘空列表[ ]空元组( )空字典{ }空集合set( )

循环外的else(当没有使用break跳出循环时执行)

>>> n = [1, 2, 3] >>> for i in n: ... if i > 3: ... break ... else: ... print('hello') ... hello >>> for i in n: ... if i > 2: ... break ... else: ... print('hello') ... >>>

使用zip()并行迭代(在最短序列处停止)

>>> a = [1, 2, 3] >>> b = (5, 6, 7, 8, 9, 10) >>> x = zip(a, b) >>> type(x) <class 'zip'> >>> for i in x: ... print(i) ... (1, 5) (2, 6) (3, 7)

像切片一样使用range()

>>> list(range(0, 3)) [0, 1, 2] >>> list(range(10, -1, -1)) [10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0] >>> list(range(0, 11, 2)) [0, 2, 4, 6, 8, 10]

推导式

列表推导式

>>> a = [num for num in range(1, 11)] >>> a [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] >>> a = [num for num in range(1, 11) if num % 2 == 0] >>> a [2, 4, 6, 8, 10] >>> a = [(x, y) for x in range(3) for y in range(3)] >>> a [(0, 0), (0, 1), (0, 2), (1, 0), (1, 1), (1, 2), (2, 0), (2, 1), (2, 2)]

字典推导式

>>> word = 'letters' >>> d = {letter: word.count(letter) for letter in set(word)} >>> d {'e': 2, 'l': 1, 't': 2, 's': 1, 'r': 1}

集合推导式(类似列表推导式)

>>> a = {num for num in range(4)} >>> a {0, 1, 2, 3} >>> type(a) <class 'set'>

生成器推导式(可直接进行迭代,但只能使用一次)

>>> a = (num for num in range(4)) >>> type(a) <class 'generator'> >>> list(a) [0, 1, 2, 3] >>> list(a) []

函数

函数参数是以元组形式进行传递

函数参数

位置参数(必须记住每个位置的参数的含义)

>>> def test(x, y, z): ... print('x = %d y = %d z = %d' % (x, y, z)) ... >>> test(1, 2, 3) x = 1 y = 2 z = 3

关键字参数(调用函数时直接指定参数名字,可调参数顺序)

>>> test(x = 3, z = 1, y = 2) x = 3 y = 2 z = 1

默认参数

默认参数的右边不能有非默认参数,默认参数值在函数被定义时已经计算出来,而不是在程序运行时,所以不要把可变数据类型当作默认参数值

>>> def test(x, y, z = 3): ... print('x = %d y = %d z = %d' % (x, y, z)) ... >>> test(1, 2) x = 1 y = 2 z = 3 >>> test(1, 2, 4) x = 1 y = 2 z = 4 >>> def test(x, y = 2, z): ... print('x = %d y = %d z = %d' % (x, y, z)) ... File "<stdin>", line 1 SyntaxError: non-default argument follows default argument

使用 * 收集位置参数(主要用于接收可变数量的参数)

>>> def test(*args): ... print('Positional argument tuple:', args) ... >>> test(1, 2, 3) Positional argument tuple: (1, 2, 3) >>> test('a', 'b', 'c', 'd', 'e') Positional argument tuple: ('a', 'b', 'c', 'd', 'e')

使用 ** 收集关键字参数

>>> def test(**kwargs): ... print('Keyword arguments:', kwargs) ... >>> test(x = 1, y = 2, z = 3) Keyword arguments: {'x': 1, 'y': 2, 'z': 3} >>> test(x = 'a', z = 'b', y = 'c') Keyword arguments: {'x': 'a', 'z': 'b', 'y': 'c'}

如果混合使用 * 与 ** 那么参数必须按照顺序出现

>>> def test(*args, **kwargs): ... print('P: ', args) ... print('K: ', kwargs) ... >>> test(1, 2, 3, x = 4, y = 5) P: (1, 2, 3) K: {'x': 4, 'y': 5} >>> test(1, x = 2, 3) File "<stdin>", line 1 SyntaxError: positional argument follows keyword argument
文档字符串

相当于函数注释,可使用help()或print()显示文档字符串

>>> def test(anything): ... 'This is a func' ... return anything ... >>> def test2(allthing): ... ''' ... This is a func2 ... ''' ... return allthing ... >>> help(test) Help on function test in module __main__: test(anything) This is a func >>> print(test2.__doc__) This is a func2 >>>
函数类型

内部函数

>>> def outer(a, b): ... def inner(c, d): ... return c + d ... return inner(a, b) ... >>> outer(4, 7) 11

闭包

>>> def test(saying): ... def inner(): ... return 'You said : %s' % saying ... return inner ... >>> a = test('haha') >>> type(a) <class 'function'> >>> a() 'You said : haha'

匿名函数( 冒号前为参数,后为返回值)

>>> def test(ls, func): ... for i in ls: ... print(func(i)) ... >>> a = [1, 2, 3] >>> test(a, lambda item: item * item) 1 4 9

内部函数与闭包用法比较

内部函数创建后被调用,闭包则直接返回创建的新函数内部函数一般不直接使用外部变量,闭包则直接使用
生成器

生成器是用来创建Python 序列的一个对象。使用它可以迭代庞大的序列,且不需要在内 存中创建和存储整个序列

>>> def one2ten(): ... i = 1 ... while i < 11: ... yield i ... i += 1 ... >>> g = one2ten() >>> for i in g: ... print(i) ... 1 2 3 4 5 6 7 8 9 10
装饰器

主要用于在不修改函数源代码的情况下修改函数 装饰器实际上是一个函数,接受一个函数作为参数返回另一个函数,使用的主要技巧:

*args **kwargs闭包作为参数的函数

单装饰器

>>> def docu(func): ... def new_func(*args, **kwargs): ... print('start :', func.__name__) ... result = func(*args, **kwargs) ... print('end :', func.__name__) ... return result ... return new_func ... >>> def test(a, b): ... return a + b ... >>> a = docu(test) >>> a(1, 2) start : test end : test 3 >>> @docu ... def test2(c, d): ... return c + d ... >>> test2(1, 2) start : test2 end : test2 3

多装饰器(靠近函数的先执行)

>>> def square(func): ... def new_func(*args, **kwargs): ... result = func(*args, **kwargs) ... result *= result ... print('square result: ', result) ... return result ... return new_func ... >>> >>> @docu ... @square ... def test3(x, y): ... return x + y ... >>> test3(1, 2) start : new_func square result: 9 end : new_func 9 >>> >>> @square ... @docu ... def test4(x, y): ... return x + y ... >>> test4(1, 1) start : test4 end : test4 square result: 4 4

命名空间和作用域

函数内如果先引用全局变量再修改则会报错,反过来先修改再引用则不会(后者实际是声明了同名的局部变量)

>>> def test(): ... print('animal: ', animal) ... >>> test() animal: cat >>> def test2(): ... print('in test2 animal: ', animal) ... animal = 'dog' ... >>> test2() Traceback (most recent call last): File "<stdin>", line 1, in <module> File "<stdin>", line 2, in test2 UnboundLocalError: local variable 'animal' referenced before assignment

使用global读取全局变量

>>> animal = 'cat' >>> def test(): ... global animal ... animal = 'dog' ... print('animal: ', animal) ... >>> test() animal: dog >>> animal 'dog'

Python 提供了两个获取命名空间内容的函数

locals() 返回一个局部命名空间内容的字典globals() 返回一个全局命名空间内容的字典

>>> animal = 'cat' >>> def test(): ... animal = 'dog' ... print('local: ', locals()) ... >>> test() local: {'animal': 'dog'} >>> globals() {'__name__': '__main__', '__doc__': None, '__package__': None, '__loader__': <class '_frozen_importlib.BuiltinImporter'>, '__spec__': None, '__annotations__': {}, '__builtins__': <module 'builtins' (built-in)>, 'animal': 'cat', 'test': <function test at 0x02BDD588>, 'test2': <function test2 at 0x04F94B70>}

以两个下划线__ 开头和结束的名称都是Python 的保留用法

>>> def test(): ... 'document' ... print('test func') ... >>> test.__name__ 'test' >>> test.__doc__ 'document'

异常

捕获所有异常

>>> ls = [1, 2, 3] >>> try: ... ls[6] ... except: ... print('error') ... error

捕获特定异常

>>> ls = [1, 2, 3] >>> try: ... ls[6] ... except IndexError as err: ... print(err) ... list index out of range

编写自己的异常

>>> class CosError(Exception): ... pass ... >>> ls = ['haha', 'cos', 'hehe'] >>> for i in ls: ... if i == 'cos': ... raise CosError(i) ... Traceback (most recent call last): File "<stdin>", line 3, in <module> __main__.CosError: cos

模块、包和程序

命令行参数

import sys print('Argument: ', sys.argv) --- python test.py Argument: ['test.py'] --- python test.py 1 2 a b Argument: ['test.py', '1', '2', 'a', 'b']

模块和import语句

直接导入

import random

别名导入

import random as rd

全局导入(全局可见)

import random xxx xxx xxx

局部导入(局部可见)

ls = [1, 2, 3] def test(): import random xxx xxx

部分导入

>>> from random import choice as ch >>> ls = [1, 2, 3] >>> ch(ls) 2

模块搜索路径

Python 会在什么地方寻找文件来导入模块?使用命名为path 变量的存储在标准sys 模块 下的一系列目录名和ZIP 压缩文件 第一个匹配到的模块会先被使用,这也就意味着如果你在标准库之前的搜索路径上定义一 个模块random,就不会导入标准库中的random 模块

>>> import sys >>> for p in sys.path: ... print(p) ... C:\Users\xxxxx\AppData\Local\Programs\Python\Python36-32\python36.zip C:\Users\xxxxx\AppData\Local\Programs\Python\Python36-32\DLLs C:\Users\xxxxx\AppData\Local\Programs\Python\Python36-32\lib C:\Users\xxxxx\AppData\Local\Programs\Python\Python36-32 C:\Users\xxxxx\AppData\Local\Programs\Python\Python36-32\lib\site-packages

Python标准库

处理字典缺失的键

函数setdefault (键不存在时在字典中添加一项)

>>> d = {'a' : 1, 'b': 2} >>> t = d.setdefault('c', 3) >>> t 3 >>> t = d.setdefault('c', 4) >>> t 3

函数defaultdict (创建字典时为每个键指定默认值,参数为函数用于设置默认值)

>>> from collections import defaultdict >>> d = defaultdict(int) >>> d['a'] 0 >>> d['b'] 0 >>> d defaultdict(<class 'int'>, {'a': 0, 'b': 0}) >>> def fl(): ... return 2.0 ... >>> d2 = defaultdict(fl) >>> d2['a'] 2.0
使用Counter计数

交集取两者中较小值,并集取两者中较大值

>>> from collections import Counter >>> ls = ['a', 'a', 'b', 'a'] >>> ls2 = ['b', 'b', 'd'] >>> ls_counter = Counter(ls) >>> ls_counter Counter({'a': 3, 'b': 1}) >>> ls_counter.most_common() [('a', 3), ('b', 1)] >>> ls_counter.most_common(1) [('a', 3)] >>> ls2_counter = Counter(ls2) >>> ls_counter + ls2_counter Counter({'a': 3, 'b': 3, 'd': 1}) >>> ls_counter - ls2_counter Counter({'a': 3}) >>> ls2_counter - ls_counter Counter({'b': 1, 'd': 1}) >>> ls_counter & ls2_counter Counter({'b': 1}) >>> ls_counter | ls2_counter Counter({'a': 3, 'b': 2, 'd': 1})
双端队列:栈+队列

deque 是一种双端队列,同时具有栈和队列的特征。它可以从序列的任何一端添加和删除 项

>>> from collections import deque >>> s = 'abcdcba' >>> dq = deque(s) >>> while len(dq) > 1: ... if dq.popleft() != dq.pop(): ... break ... else: ... print('ok') ... ok
使用itertools迭代代码结构

串联多个可迭代对象

>>> import itertools >>> for i in itertools.chain(['a', 'b'], [1, 2]): ... print(i) ... a b 1 2

可迭代对象循环

>>> import itertools >>> for i in itertools.cycle([1, 2, 3]): ... print(i) ... 1 2 3 1 ...

计算累积值(accumulate接收函数参数,该函数必须接收两个参数并返回单个值)

>>> import itertools >>> for i in itertools.accumulate([1, 2, 3]): ... print(i) ... 1 3 6 >>> def mul(x, y): ... return x * y ... >>> for i in itertools.accumulate([1, 2, 3], mul): ... print(i) ... 1 2 6

对象和类

继承和覆盖

子类可继承父类所有方法(包括__init__ 方法),也可以覆盖父类的任何方法

继承

>>> class test(): ... def __init__(self, name): ... self.name = name ... >>> class test2(test): ... pass ... >>> a = test2('haha') >>> a.name 'haha'

覆盖(同名即为覆盖,没有重载的概念)

>>> class t(): ... def say(self, name): ... print(name) ... >>> class t2(t): ... def say(self, name, word): ... print(name, word) ... >>> a = t2() >>> a.say('haha', 'hehe') haha hehe >>> a.te('haha') Traceback (most recent call last): File "<stdin>", line 1, in <module> TypeError: say() missing 1 required positional argument: 'word'

使用super从父类得到帮助

当父类方法被覆盖而又需要调用父类方法时使用super

>>> class test(): ... def __init__(self, name): ... self.name = name ... >>> class test2(test): ... def __init__(self, name, email): ... super().__init__(name) ... self.email =email ... >>> a = test2('haha', '123@.com') >>> a.name 'haha' >>> a.email '123@.com'

使用super的实际过程

获取父类定义自动将子类对象作为参数传递给父类被调用函数传入被调用函数所需其余参数执行被调用函数

继承时,应该让类完成自己应该完成的事。所以以上代码并没有写成如下形式

>>> class test2(test): ... def __init__(self, name, email): ... self.name = name ... self.email =email

self的自辩

Python 使用self 参数来找到正确的对象所包含的特性和方法

>>> class test(): ... def say(self): ... print('haha') ... >>> a = test() >>> a.say() haha >>> test.say(a) haha

调用类的实例方法的实际过程

寻找类对象所属类的定义把对象作为self参数传给所属类的被调用方法

使用属性对特性进行访问和设置

Python里所有特性(attribute)都是公开的

使用property(属性)设置特性

>>> class test(): ... def __init__(self, name): ... self.hide_name = name ... def get_name(self): ... print('inside the getter') ... return self.hide_name ... def set_name(self, name): ... print('inside the setter') ... self.hide_name = name ... name = property(get_name, set_name) ... >>> a = test('haha') >>> a.name inside the getter 'haha' >>> a.name = 'hehe' inside the setter >>> a.name inside the getter 'hehe'

使用修饰符@设置特性(@property相当于getter)

>>> class test(): ... def __init__(self, name): ... self.hide_name = name ... @property ... def name(self): ... print('inside the getter') ... return self.hide_name ... @name.setter ... def name(self, name): ... print('inside the setter') ... self.hide_name = name ... >>> a = test('haha') >>> a.name inside the getter 'haha' >>> a.name = 'hehe' inside the setter >>> a.name inside the getter 'hehe'

可以只设置getter使得特性无法被修改(不过不建议只设置setter)

>>> class test(): ... def __init__(self, name): ... self.hide_name = name ... def getter(self): ... return self.hide_name ... name = property(getter) ... >>> a = test('haha') >>> a.name 'haha' >>> a.name = 'hehe' Traceback (most recent call last): File "<stdin>", line 1, in <module> AttributeError: can't set attribute >>> class test(): ... def __init__(self, name): ... self.hide_name = name ... @property ... def name(self): ... return self.hide_name ... >>> a = test('hehe') >>> a.name 'hehe' >>> a.name = 'haha' Traceback (most recent call last): File "<stdin>", line 1, in <module> AttributeError: can't set attribute

使用名称重整保护私有特性

Python对那些需要刻意隐藏在类内部的特性有自己的命名规范:由连续的两个下划线开头(__)

只设置属性类外部仍能通过特性名直接访问特性,为防止这种情况以双下划线开头命名特性

>>> class test(): ... def __init__(self, name): ... self.__name = name ... @property ... def name(self): ... return self.__name ... @name.setter ... def name(self, name): ... self.__name = name ... >>> a = test('haha') >>> a.name 'haha' >>> a.name = 'hehe' >>> a.name 'hehe' >>> a.__name Traceback (most recent call last): File "<stdin>", line 1, in <module> AttributeError: 'test' object has no attribute '__name'

名称重整实际上并没有把变量变成私有,但确实让外部代码无法使用

>>> a._test__name 'hehe'

方法的类型

实例方法

以self 作为第一个参数的方法都是实例方法(instance method)。实例方法的首个参数是self,当它被调用时,Python 会把调用该方法的对象作为self 参数传入

类方法

以@classmethod修饰,与实例方法类似,第一个参数cls为类本身

>>> class test(): ... count = 0 ... def __init__(self): ... test.count += 1 ... @classmethod ... def kids(cls): ... print('Test has', cls.count, 'kids') ... >>> a = test() >>> b = test() >>> c = test() >>> test.kids() Test has 3 kids
静态方法

以@staticmethod修饰,不需要self和cls作为参数,可通过实例调用或类名直接调用,可调用类特性不能调用实例特性

>>> class test(): ... count = 0 ... def __init__(self, name): ... test.count += 1 ... self.name = name ... @staticmethod ... def say(): ... print(test.count) ... print(self.name) ... >>> a = test('haha') >>> b = test('hehe') >>> test.say() 2 Traceback (most recent call last): File "<stdin>", line 1, in <module> File "<stdin>", line 9, in say NameError: name 'self' is not defined >>> a.say() 2 Traceback (most recent call last): File "<stdin>", line 1, in <module> File "<stdin>", line 9, in say NameError: name 'self' is not defined

鸭子类型

如果它像鸭子一样走路,像鸭子一样叫,那么它就是一只鸭子

Python多态的形式,我们可以对不同对象调用同名操作(只要它具有这种操作)而不必管对象的类型是什么

>>> class man(): ... def say(self): ... print('I am man') ... >>> class tiger(): ... def say(self): ... print('I am tiger') ... >>> def what(obj): ... obj.say() ... >>> m = man() >>> t = tiger() >>> what(m) I am man >>> what(t) I am tiger

魔术方法

魔术方法名称以双下划线开头和结束

>>> class word(): ... def __init__(self, text): ... self.text = text ... def __eq__(self, other): ... return self.text == other.text ... >>> a = word('haha') >>> b = word('haha') >>> c = word('hehe') >>> a == b True >>> a == c False

常用魔术方法

方法名使用__eq__(self, other)self == other__ne__(self, other)self != other__lt__(self, other)self < other__gt__(self, other)self > other__le__(self, other)self <= other__ge__(self, other)self >= other__add__(self, other)self + other__sub__(self, other)self - other__mul__(self, other)self * other__floordiv__(self, other)self // other__truediv__(self, other)self / other__mod__(self, other)self % other__pow__(self, other)self ** other

何时使用类和对象而不是模块

来自创始人——Guido van Rossum的建议:

不要过度构建数据结构。尽量使用元组(以及命名元组)而不是对象。尽量使用 简单的属性域而不是getter/setter 函数……内置数据类型是你最好的朋友。尽可 能多地使用数字、字符串、元组、列表、集合以及字典。多看看容器库提供的类 型,尤其是双端队列。

命名元组

命名元组是元组的子类,你既可以通过名称(使用.name)来访问其中的值,也可以通过 位置进行访问(使用[offset])。

创建命名元组

>>> from collections import namedtuple >>> a = namedtuple('t_name', 'one two') >>> b = a('hi', 'hello') >>> b t_name(one='hi', two='hello') >>> d = {'one': 1, 'two': 2} >>> a2 = a(**d) >>> a2 t_name(one=1, two=2)

命名元组不可更改,但可替换某些值后返回新的元组

>>> a3 = a2._replace(one = 'haha', two = 'hehe') >>> a3 t_name(one='haha', two='hehe')

像高手一样玩转数据

Unicode

根据名称返回字符与根据字符返回名称(如果使用的字体无该符号则以占位符形式出现)

>>> import unicodedata >>> unicodedata.name('A') 'LATIN CAPITAL LETTER A' >>> unicodedata.lookup('LATIN CAPITAL LETTER A') 'A'

为了方便查阅,Unicode 字符名称索引页列出的字符名称是经过修改的,因此与由name() 函数得到的名称有所不同。如果需要将它们转化为真实的Unicode 名称(Python 使用的),只需将逗号舍去,并将逗号后面的内容移到最前面即可。据此,我们应将E WITH ACUTE, LATIN SMALL LETTER 改为LATINSMALL LETTER E WITH ACUTE:

字符串中直接使用Unicode字符

>>> a = '\N{LATIN SMALL LETTER U WITH DIAERESIS}' >>> a 'ü'

UTF-8 动态编码方案

为ASCII 字符分配1 字节为拉丁语系(除西里尔语)的语言分配2 字节为其他的位于基本多语言平面的字符分配3 字节为剩下的字符集分配4 字节,这包括一些亚洲语言及符号

len()中Unicode编码返回字符个数,其他编码返回字节数

>>> a = '\u2603' >>> len(a) 1 >>> b = a.encode('utf-8') >>> len(b) 3

格式化

旧式格式化
符号含义%s字符串%d十进制%x十六进制%o八进制%f十进制浮点数%e科学记数法浮点数%g十进制或科学记数法表示的浮点数%%%本身

旧式常见格式化

>>> a = 42 >>> b = 1.23 >>> c = 'string' >>> '%d %f %s' % (a, b, c) '42 1.230000 string' >>> 'd f s' % (a, b, c) ' 42 1.230000 string' >>> '%-10d %-10f %-10s' % (a, b, c) '42 1.230000 string ' >>> '.4d .4f .4s' % (a, b, c) ' 0042 1.2300 stri' >>> '%.4d %.4f %.4s' % (a, b, c) '0042 1.2300 stri' >>> '%*.*d %*.*f %*.*s' % (10, 4, a, 10, 4, b, 10, 4, c) ' 0042 1.2300 stri'

新式常见格式化(无法对整数设置精度)

>>> '{} {} {}'.format(a, b, c) '42 1.23 string' >>> '{2} {0} {1}'.format(a, b, c) 'string 42 1.23' >>> '{a} {b} {c}'.format(a = 42, b = 1.23, c = 'string') '42 1.23 string' >>> '{0:d} {1:f} {2:s}'.format(a, b, c) '42 1.230000 string' >>> '{a:d} {b:f} {c:s}'.format(a = 42, b = 1.23, c = 'string') '42 1.230000 string' >>> '{0:10d} {1:10f} {2:10s}'.format(a, b, c) ' 42 1.230000 string ' >>> '{0:>10d} {1:>10f} {2:>10s}'.format(a, b, c) ' 42 1.230000 string' >>> '{0:^10d} {1:^10f} {2:^10s}'.format(a, b, c) ' 42 1.230000 string ' >>> '{0:^10d} {1:^10.1f} {2:^10.5s}'.format(a, b, c) ' 42 1.2 strin ' >>> '{0:^10.3d} {1:^10.1f} {2:^10.5s}'.format(a, b, c) Traceback (most recent call last): File "<stdin>", line 1, in <module> ValueError: Precision not allowed in integer format specifier
转载请注明原文地址: https://www.6miu.com/read-1400285.html

最新回复(0)