《Python语言及其应用》的学习笔记
一、Python基本元素:数字、字符串和变量
Python基本数据类型(不可变):
bool, int, float, str
1. 变量
变量名只能包含大小写字母、数字、下划线,开头不能为数字
type()检查对象的类型: type('hello') # <class 'str'>
2. 数字
常见运算: +
, -
, *
, /
(浮点数除法,结果为小数), //
(整除,结果为整数), %
(求余), **
(幂)
自运算: -=
, +=
, *=
, /=
, ...
类型转换: int(), float()
隐式转换: int + float = float
, bool + int = int
divmod(9, 5) # (1, 4) 类似于(9 // 5, 9 % 5)
3. 字符串
三元引号用于创建多行字符串: 每一行的换行符以及行首和行尾的空格都会被保留
single = 'hello world'
multi = '''
hello
world
'''
print(len(single)) # 11
print(len(multi)) # 17
复制代码
类型转换: str()
转义字符: \n, \t, \', \", \\, \000(空格)
常用操作:
- 拼接
+
:'a' + 'b' # ab
- 复制
*
:'a' * 3 # aaa
- 提取单个字符
[]
:'abc'[1] # b
(超过偏移量报错) - 切片
[start:end:step]
(不包括end
):[:]
复制整个字符[start:]
从start到结尾[:end]
从开头到end-1[start:end]
从start到end-1[start:end:step]
从start到end-1, 每step个字符提取一个[-n:]
最后n个[::-1]
反向, 等同于[-1::-1]
- 对于超过偏移量的,start当作0, end当作-1
len()
获取长度split()
分割(默认使用空白字符-\n,\t,\000):'a,b,c'.split(',') # ['a', 'b', 'c']
join()
合并:','.join(['a', 'b', 'c']) # 'a,b,c'
字符串常用方法:
str.startswith('a')
, 是否以'a'
开头str.endswith('a')
, 是否以'a'
结尾str.find('a')
, 查询第一次出现'a'
的位置str.rfind('a')
, 查询最后一次出现'a'
的位置str.count('a')
, 统计'a'
出现的次数str.strip()
, 移除头尾指定的字符(默认为空格)str.capitalize()
, 首字母大写str.title()
, 所有单词的开头字母都大写str.lower()
, 小写str.upper()
, 大写str.swapcase()
, 大小写互换str.replace('a ', 'hello', count)
, 字符串替换,count默认替换所有实例
二、Python容器:列表、元组、字典、集合
1. 列表(list: 可变、有序、重复)
创建列表: list()
或者[]
转换:
- 字符串:
list('abc') # ['a', 'b', 'c']
- 元组:
list(('a', 'b', 'c')) # ['a', 'b', 'c']
- split():
'a,b,c'.split(',') # ['a', 'b', 'c']
使用[offset]
获取和修改元素((超过偏移量会报错))
使用切片[start:end:step]
提取部分列表(同字符串切片)
操作数组:
list.append(x)
尾部添加元素list.extend(x)或+=
合并列表list.insert(i, x)
指定位置之前插入元素del list[i]
删除指定位置的元素list.remove(x)
删除具有指定值的元素(只删除匹配的第一个元素)list.pop(i)
获取并删除指定位置的元素,pop(0)
头部、pop()
或pop(-1)
尾部list.index(x)
返回列表中第一个值为 x 的元素的索引in
判断值是否存在list.count(x)
记录x出现的次数', '.join(list)
转换为字符串list.sort()
改变list,sorted(list)
不改变list,而是生成其副本,参数reverse=True
改为降序排序len(list)
获取长度
数组复制:
- copy函数:
a.copy()
- list()转换函数:
list(a)
- 切片:
a[:]
2. 元组(tuple: 不可变)
元组占用空间小
不会意外修改元组的值
可以用作字典的键
命名元组可以替代对象
函数的参数是以元组的形式传递的
# 创建元组
empty_tuple = ()
one_char = 'a',
char_tuple = 'a', 'b', 'c'
character = ('a', 'b', 'c')
# 元组解包
a, b, c = character
# 互换
b, a = a, b
# 转换
tuple(list)
复制代码
3. 字典(dict: 可变)
创建字典: {}
转换:dict()
(将包含双值子序列的序列转换为字典)
lol = [['a', 1], ['b', 2], ['c', 3]] # (a list of two-item list)
lot = [('a', 1), ('b', 2), ('c', 3)] # (a list of two-item tuple)
tol = (['a', 1], ['b', 2], ['c', 3]) # (a tuple of two-item list)
los = ['a1', 'b2', 'c3']
tos = ('a1', 'b2', 'c3')
dict(lol) # {'a': 1, 'b': 2, 'c': 3}
dict(lot) # {'a': 1, 'b': 2, 'c': 3}
dict(tol) # {'a': 1, 'b': 2, 'c': 3}
dict(los) # {'a': '1', 'b': '2', 'c': '3'}
dict(tos) # {'a': '1', 'b': '2', 'c': '3'}
复制代码
常用操作
dict.update(d)
合并字典,新规入的字典的值取代原有的值del dict[key]
删除具有指定键的元素dict.clear()
删除所有元素in
判断是否存在dict.get(key, default)
获取元素,不存在时,返回默认值(默认为None
),(dict[key]
获取不到时会报错)dict.keys()
获取所有的键(list(dict.keys())
转换为list
)dict.values()
获取所有的键(list(dict.values())
转换为list
)dict.items()
获取所有的键(list(dict.items())
转换为list
)dict.copy()
复制
4. 集合(set: 无序、不重复、可变)
集合就像舍弃了值, 仅剩下键的字典
创建集合: set()
, {1, 3, 6, 9}
转换:
set('letter') # {'l', 'r', 't', 'e'}
set(['a', 'b', 'c']) # {'c', 'b', 'a'}
set(('a', 'b', 'c')) # {'c', 'b', 'a'}
set({'a': 1, 'b': 2, 'c': 3}) # {'c', 'b', 'a'}
复制代码
in
检查是否存在
运算符:
a = {1, 2}
b = {2, 3}
& 交集(a.intersection(b))
a & b # {2}
| 并集(a.union(b))
a | b # {1, 2, 3}
- 差集(a.difference(b))(出现在第一个集合但不出现在第二个集合)
a - b # {1}
^ 异或集(a.symmetric_difference(b))(两个集合中的不同元素)
a ^ b # {1, 3}
<= 判断子集(a.issubset(b))
a <= b # False
>= 判断真集(a.issuperset(b))
a >= b # False
复制代码
三、Python代码结构
1. #
注释
Python没有多行注释
2. \
连接
把一段长代码分成多行()
# 拼接长字符串
alphabet = ''
alphabet += 'abc'
alphabet += 'def'
# 使用\
alphabet = 'abc' + \
'def'
1 + 2 + 3
# 使用\
1 + 2 + \
3
复制代码
3. if elif else
条件判断
num = 2
if num == 1:
print('This is one')
elif num === 2:
print('This is two')
else:
print('I don\'t known')
复制代码
判断假值
类型 | 假值 |
---|---|
bool | False |
null类型 | None |
int | 0 |
float | 0.0 |
str | '' |
list | [] |
tuple | () |
dict | {} |
set | set() |
4. while
循环
# 读入整数,如果是奇数则输出其平方数,偶数则跳过,q来结束循环
while True:
value = input('Integer, please [q to quit]: ')
if value == 'q':
break # break 跳出循环
number = int(value)
if number % 2 == 0:
continue # 跳出本次循环,继续下一个循环
print(number, 'squared is', number**2)
复制代码
循环外使用else: 如果while循环正常结束(没有使用break跳出),程序将执行可选的else片段
5. for...in
迭代
list, str, tuple, dict, set都是可迭代的对象
break, continue, else和while一样
range(start, stop, step)
生成自然数序列(不包括stop)
zip()
并行迭代
alphabet = ['a', 'b', 'c']
number = [1, 2, 3, 4]
for c, n in zip(alphabet, number):
print(c, n)
# 在最短序列用完时停止
# a 1
# b 2
# c 3
# 配对两个元组
list(zip(alphabet, number)) # [('a', 1), ('b', 2), ('c', 3)]
# 字典
dict(zip(alphabet, number)) # {'c': 3, 'a': 1, 'b': 2}
复制代码
6. 推导式
列表推导式:
# [expression for item in iterable]
number_list = [x for x in range(3)] # [0, 1, 2]
# [expression for item in iterable if condition]
a_list = [x for x in range(10) if x % 2 == 0] # [0, 2, 4, 6, 8]
# 嵌套循环
rows = range(1, 4)
cols = range(1, 3)
# 传统
for row in rows:
for col in cols:
print(row, col)
# 推导式
cells = [(row, col) for row in rows for col in cols]
for row, col in cells:
print(row, col)
复制代码
字典推导式:
word = 'letters'
letter_counts = {letter: word.count(letter) for letter in word}
# {'e': 2, 'l': 1, 'r': 1, 't': 2, 's': 1}
复制代码
集合推导式:
a_set = {number for number in range(1, 6) if number % 2 == 1}
# {1, 3, 5}
复制代码
生成器推导式: (元组没有推导式)
number_thing = (number for number in range(1, 6))
type(number_thing) # <class 'generator'>
for number in number_thing:
print(number)
# 转换为list(一个生成器只运行一次,只在运行中产生值)
list(number_thing) # [1, 2, 3, 4, 5]
list(number_thing) # []
复制代码
7. 函数
使用is
判断None
def is_none(thing):
if thing is None:
print('It\'s None')
elif thing:
print('It\'s True')
else:
print('It\'s False')
is_none(None) # It's None
is_none([]) # It's False
is_none(1) # It's True
复制代码
参数 默认参数在函数被定义时就已经计算出来了
# bug
def buggy(arg, result=[]):
result.append(arg)
print(result)
buggy('a') # ['a']
buggy('b') # ['a', 'b']
# fix
def buggy(arg, result=None):
if result is None:
result = []
result.append(arg)
print(result)
buggy('a') # ['a']
buggy('b') # ['b']
复制代码
def ours(first, middle, last):
return {'first': first, 'middle': middle, 'last': last}
ours(1, 3, 7) # 位置参数
ours(1, 3, last=5) # 关键字参数(关键字参数必须跟随在位置参数的后面)
# 使用*收集位置参数: 将一组可变数量的位置参数集合成参数值的元组
def print_args(required1, required2, *args):
print(required1, required2, args)
print_args(1, 2) # 1 2 ()
print_args(1, 2, 3, 4, 5) # 1 2 (3, 4, 5)
# 使用**收集关键字参数: 将关键字参数收集到一个字典中
def print_kwargs(required1, *args, **kwargs):
print(required1, args, kwargs)
print_kwargs(1, 2, 3, a=4, b=5) # 1 (2, 3) {'b': 5, 'a': 4}
复制代码
闭包:
def outer(num):
def inner():
return 'This is %d' % num
return inner
a = outer(1)
b = outer(2)
print(a()) # This is 1
print(b()) # This is 2
复制代码
lambda()函数:
def edit_story(words, func):
for word in words:
print(func(word))
edit_story(['hello', 'bye', 'see'], lambda word: word.capitalize() + '!')
# Hello!
# Bye!
# See!
复制代码
8. 生成器
调用生成器函数,返回一个generator对象,供迭代器产生数据
def my_range(first=0, last=10, step=1):
number = first
while number < last:
yield number
number += step
for x in my_range(1, 5):
print(x)
复制代码
9. 装饰器
在不改变源代码的情况下修改已经存在的函数
def document_it(func):
def new_func(*args, **kwargs):
print('Running function:', func.__name__)
print('arguments:', args, kwargs)
result = func(*args, **kwargs)
print('Result:', result)
return result
return new_func
@document_it
def add_ints(a, b):
print('...execute...')
return a + b
# 等价于
# def add_ints(a, b):
# print('...execute...')
# return a + b
# cooler_add_ints = document_it(add_ints)
add_ints(2, 4)
# Running function: add_ints
# arguments: (2, 4) {}
# ...execute...
# Result: 6
复制代码
多个装饰器时,靠近def的装饰器最先执行
10. 命名空间和作用域
name = 'a' # global
def print_global_name():
print(name, id(name))
def print_local_name():
name = 'b' # local
print(name, id(name))
def change_global_name():
global name # 修改全局变量之前先在变量前面显式声明global
name = 'b'
print(name, id(name))
print_global_name() # a 61125472
print_local_name() # b 61127936
print(name, id(name)) # a 61125472
change_global_name() # b 61127936
print(name, id(name)) # b 61127936
复制代码
11. try...except处理异常
short_list = [1, 2, 3]
while True:
value = input('Position [q to quit]?')
if value == 'q':
break
try:
position = int(value)
print(short_list[position])
except IndexError as err:
print('Bad index:', position)
except Exception as other:
print('Something else broken:', other)
复制代码
四、Python盒子: 模块、包和程序
1. 模块
一个模块就是一个Python代码文件
导入模块:
import random # 全部导入
from random import choice # 部分导入
from random import choice as select # 使用别名
复制代码
搜索路径: 第一个匹配到的模块会先被使用
import sys
for place in sys.path:
print(place)
复制代码
2. 包
多个模块组织成文件层次,称为包(记得加个__init__.py文件)
# 包sourses
# sourses/
# __init__.py
# a.py
# b.py
from sourses import a, b
复制代码
3. Python标准库
使用setdefault()和defaultdict()处理缺失的键
# setdefault: 如果键不存在则添加键以及默认值,否则不做操作
char_dict = {'a': 1, 'b': 2}
char_dict.setdefault('c', 3) # {'b': 2, 'a': 1, 'c': 3}
char_dict.setdefault('b', 3) # {'b': 2, 'a': 1, 'c': 3}
# defaultdict为每个键都指定默认值
# int() -> 0, list() -> [], dict() -> {}, lambda: 'hello' -> 'hello'
from collections import defaultdict
color_counter = defaultdict(int)
for color in ['red', 'green', 'red', 'blue']:
color_counter[color] += 1
dict(color_counter) # {'red': 2, 'blue': 1, 'green': 1}
# 等价于
color_counter = {}
for color in ['red', 'green', 'red', 'blue']:
if not color in color_counter:
color_counter[color] = 0
color_counter[color] += 1
复制代码
使用Counter()计数
from collections import Counter
colors = ['red', 'green', 'red', 'blue']
color_counter = Counter(colors) # Counter({'red': 2, 'blue': 1, 'green': 1})
# most_common以降序返回指定数目元素, 默认返回全部
color_counter.most_common(2) # [('red', 2), ('blue', 1)]
复制代码
使用有序字典OrderedDict按键排序(键添加的顺序)
from collections import OrderedDict
quotes = OrderedDict([
('a', 1),
('b', 2),
('c', 3)
])
复制代码
五、对象和类
1. 类、继承、覆盖方法、添加新方法、super、self
# Man继承自Person并覆盖Person的__init__方法,添加talk新方法,同时在__init__方法中调用父类的__init__方法
# 实例调用方法时:先查找类,然后把实例当作self参数传给类所包含的方法,eg. man.talk -> Man.talk(man)
class Person():
def __init__(self, name):
self.name = name
def speak(self):
print('I\'m {}'.format(self.name))
class Man(Person):
def __init__(self, name):
super().__init__(name) # super()获得父类Person, 等同于Person.__init__(self, name)
self.sex = sex
def talk(self):
print('I can talk.')
man = Man('Jack')
man.speak()
man.talk() # 实际Man.talk(man)
复制代码
2. 使用属性(property)对特性(attribute)进行访问和设置
这里约定对象的数据指特性
# 这里hidden_name是特性,name是属性
class Duck():
def __init__(self, input_name):
self.hidden_name = input_name # hidden_name仍然可以访问到
def get_name(self):
print('---getter name---')
return self.hidden_name
def set_name(self, input_name):
print('---setter name---')
self.hidden_name = input_name
name = property(get_name, set_name)
fowl = Duck('Howard')
print(fowl.name) # 等同于fowl.get_name()
fowl.name = 'Daffy' # 等同于fowl.set_name('Daffy')
复制代码
使用修饰器
# @property, 用于指示getter方法
# @name.setter, 用于指示setter方法
class Duck():
def __init__(self, input_name):
self.hidden_name = input_name
@property
def name(self):
print('---getter name---')
return self.hidden_name
@name.setter
def name(self, input_name):
print('---setter name---')
self.hidden_name = input_name
fowl = Duck('Howard')
print(fowl.name)
fowl.name = 'Daffy'
复制代码
以双下划线开头来保护私有特性:
class Duck():
def __init__(self, input_name):
self.__name = input_name
@property
def name(self):
print('---getter name---')
return self.__name
@name.setter
def name(self, input_name):
print('---setter name---')
self.__name = input_name
fowl = Duck('Howard')
print(fowl.name)
fowl.name = 'Daffy'
print(fowl._Duck__name) # 并没有变成私有特性,只是重整了名字
复制代码
3. 方法的类型(实例方法、类方法、静态方法)
类方法:对类的改变会影响到所有实例对象,第一个参数为类本身(约定cls)
class A():
count = 0 # 类的特性
def __init__(self):
A.count += 1
@classmethod
def kids(cls):
print('A has {} objects'.format(cls.count))
a1 = A()
a2 = A()
A.kids()
复制代码
静态方法:既不影响类也不影响实例对象,不需要cls和self做参数
class Hello():
@staticmethod
def sayHello():
print('hello')
h = Hello()
h.sayHello()
复制代码
4. 鸭子类型
如果它像鸭子一样走路,像鸭子一样叫,那么它就是一只鸭子
传统多态
class Quote():
def __init__(self, person, words):
self.person = person
self.words = words
def who(self):
return self.person
def says(self):
return self.words + '.'
class QuestionQuote(Quote):
def says(self):
return self.words + '?'
class ExclamationQueto(Quote):
def says(self):
return self.words + '!'
hunter = Quote('Hunter', 'I\'m hunting wabbits')
hunted1 = QuestionQuote('Hunted1', 'What\'s up')
hunted2 = ExclamationQueto('Hunted2', 'It\'s a rabbit')
def who_says(obj):
print(obj.who(), 'says', obj.says())
who_says(hunter)
who_says(hunted1)
who_says(hunted2)
复制代码
Python鸭子类型:无论对象类型,只需要包含who()和says()就可以调用了
class Haha():
def who(self):
return 'Haha'
def says(self):
return 'hahaha...'
haha = Haha()
who_says(haha)
复制代码
5. 特殊方法(magic method)
以双下划线(__)开头和结束
比较两个对象是否相等(忽略大小写)
class Word():
def __init__(self, text):
self.text = text
def equals(self, word):
return self.text.lower() == word.text.lower()
word1 = Word('ha')
word2 = Word('HA')
word1.equals(word2)
复制代码
使用magic method: __eq__
class Word():
def __init__(self, text):
self.text = text
def __eq__(self, word):
return self.text.lower() == word.text.lower()
word1 = Word('ha')
word2 = Word('HA')
word1 == word2
复制代码
其它magic method
方法名 | 使用 |
---|---|
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 |
str(self) | str(self) |
repr(self, other) | repr(self) |
len(self, other) | len(self) |
6. 组合
继承is-a, 组合或聚合has-a
class Bill():
def __init__(self, desc):
self.desc = desc
class Tail():
def __init__(self, length):
self.length = length
class Duck():
def __init__(self, bill, tail):
self.bill = bill
self.tail = tail
def about(self):
print('This duck has a {} bill and a {} tail'.format(self.bill.desc, self.tail.length))
tail = Tail('long')
bill = Bill('wide orange')
duck = Duck(bill, tail)
duck.about()
复制代码
7. 命名元组namedtuple
from collections import namedtuple
# 第一个参数为元组名称
# 第二个参数为由多个域名组成的字符串,各个域名之间由空格隔开
Duck = namedtuple('Duck', 'bill tail')
duck = Duck('wide orange', 'long')
print(duck) # Duck(bill='wide orange', tail='long')
# 通过点号或者索引对特性进行访问(字典是通过中括号)
print(duck.bill) # wide orange
print(duck[0]) # wide orange
# 命名元组不可变
duck.color = 'red' # 报错
# 关键词变量
parts = {'bill': 'wide orange', 'tail': 'long'}
duck2 = Duck(**parts)
# 等同于
duck2 = Duck(bill='wide orange', tail='long')
复制代码