基本术语
- 属性 attribute
- 方法 method
- 接口是对象的一些属性与方法的集合,其他对象可以用接口与这对象进行交互;其他对象不需要,通常也不允许,获取对象的全部内容。
- 信息隐藏。有时候也称为封装,但是封装是一个更加宽泛的术语,被封装的数据不一定是隐藏的。
- 抽象是从内部细节中提取公共接口的过程。
- 抽象是通过公共或者私有接口进行信息封装的过程,私有接口通常与信息隐藏有关。
- 组合是将几个对象收集在一起生成一个新对象的行为。
- 聚合 vs 组合
- 继承:一个类从另一个类中继承属性与方法
- 让一个类不实现任何方法。这样一个类只会告诉我们它可以做什么,但是完全不告诉我们要如何去做,这种类叫做接口。
- 多态是根据子类的不同实现而区别对待父类的能力。
- 多种继承:允许子类从多个父类那里继承它们的功能。
- dot notation 赋值
<对象>.<属性>=<值>
- 所有方法都有一个必要参数,一般都命名为
self
- Python同时拥有构造函数
__new__
和初始化方法__init__
- 除非要做一些异乎寻常的事,否则很少用到构造函数
- 模块(module)就是Python文件
- 一个包(package)是一个目录下模块的集合,包的名字就是目录的名字,只需要在目录下添加一个名为
__init__.py
的文件(通常是空文件)就可以告诉Python这个目录是一个包 - 通常将启动代码放到一个函数中(惯例叫
main
),只有在将该模块作为脚本运行时才会执行这一函数,在被其他脚本导入时则不会执行。
class UsefulClass:
"""This class might be useful to other modules."""
pass
def main():
"""Creates a useful class and does something with it for our module."""
useful = UsefulClass()
print(useful)
if __name__ == "__main__":
main()
虚拟环境
- 通常为每个Python项目创建一个不同的虚拟环境
- 通常将虚拟环境保存在与项目中其他文件相同的目录中
- 先cd到项目目录
- 运行
venv
创建一个虚拟环境,命名为env
- 最后用一行命令来激活环境
- 完成项目后,用
deactivate
命令退出
cd project_directory
python -m venv env
source env/bin/activate # Linux或者Mac os
env/bin/activate.bat # Windows系统
类与继承
- 超类,子类
- 多重继承;最有效的形式:混入(mixin)
- 钻石继承
- 抽象基类
- 鸭子类型
- 任何拥有
__contains__
方法的类都是Container
;任何实现Container
抽象基类的类都可以使用in
关键字。in
只是__contains__
方法的语法糖。
异常
- 大部分异常都是
Exception
类的子类 -
Exception
类本身继承自BaseException
- 所有异常必须继承
BaseException
类或其子类 -
SystemExit
和KeyboardInterrupt
直接继承自BaseException
而不是Exception
-
SystemExit
异常在程序自然退出时抛出,通常是代码中调用了sys.exit
函数;设计这个异常的目的是在程序最终退出之前完成清理工作(因为清理代码通常发生在finally
语句中) -
KeyboardInterrupt
异常常见于命令行程序。当用户执行依赖于系统的按键组合中断程序时抛出,这是用户故意中断一个正在运行的程序的标准方法。与SystemExit
类似,应该在finally
块中完成清理任务。 - 当我们仅用
except
从句而不添加任何类型的异常时,将会捕获所有BaseException
的子类(不明智)。如果真的想捕获所有的异常,建议使用except Exception
。
命名元组
- Python默认禁止向
object
以及其他几个内置类型添加任意属性 - 当需要同时指定数据和行为的时候,才需要用到类和对象
- 命名元组
from collections import namedtuple
Stock = namedtuple("Stock", "symbol current high low")
stock = Stock("FB", 75.00, high=75.03, low=74.90)
-
namedtuple
构造函数接收2个参数:第一个是这个命名元组的名称,第二个是由空格分隔的属性的字符串 - 命名元组的属性一旦设定值就不能改变;如果需要修改存储的数据,用字典更合适
字典
- Python字典的键(key)要求对象必须是可哈希(hashable) 和不可变(immutable) 的。这主要是出于字典实现机制(哈希表)对查找效率和一致性的要求
- Python中自定义类的实例默认是可哈希的。这是因为:
- 默认哈希值基于对象内存地址:如果你没有重写
__hash__
方法,Python会使用对象的唯一内存地址来计算哈希值。这意味着每个新创建的实例通常都有唯一的哈希值(除非你重写了相关方法改变了这一行为)。 - 默认相等性比较基于对象身份:同样,如果你没有重写
__eq__
方法,obj1 == obj2通常只在 obj1和 obj2是同一个实例(即内存地址相同)时返回 True。
- 默认哈希值基于对象内存地址:如果你没有重写
- 这种默认行为使得类的实例满足了作为字典键的两个核心要求:
- 哈希值在生命周期内不变:只要对象存在,其内存地址不变,哈希值也就不变。
- 可用于一致性比较:通过
__eq__
方法判断是否为同一个键。
defaultdict
-
defaultdict
构造函数需要一个函数作为参数,每当访问一个字典中不存在的key时,将会不带参数地调用这个函数,并将其结果设定为默认值
from collections import defaultdict
def letter_frequency(sentence):
frequencies = defaultdict(int)
for letter in sentence:
frequencies[letter] += 1
return frequencies
- 上例中调用的函数是
int
,即整数对象的构造函数 - 如果不带参数地调用
int
,默认会返回数字0
from collections import defaultdict
num_items = 0
def tuple_counter():
global num_items
num_items += 1
return num_items, []
d = defaultdict(tuple_counter)
d['a'][1].append("hello")
d['b'][1].append("world")
d
# defaultdict(<function tuple_counter at 0x000001A8015751C0>, {'a': (1, ['hello']), 'b': (2, ['world'])})
-
d['a'][1].append("hello")
,键值a
不存在,因此会不带参数地调用tuple_counter
,得到的返回值是元组(1, [])
,然后对空list
添加上了元素hello
-
d['b'][1].append("world")
,键值b
不存在,因此会再次不带参数地调用tuple_counter
,得到的返回值是元组(2, [])
,然后对空list
添加上了元素world
Counter
- key是输入包含的项目,value是该项目出现的数量
-
most_common
方法- 传入正整数
n
,返回频率前n
的项 - 列表,元素是(key, value)
- 传入正整数
responses = [
'vanilla',
'chocolate',
'vanilla',
'vanilla',
'caramel',
'strawberry',
'vanilla'
]
print("The children voted for {} ice cream".format(
Counter(responses).most_common(1)[0][0]
))
# The children voted for vanilla ice cream
Counter(responses).most_common(1)
# [('vanilla', 4)]
Counter(responses).most_common(2)
# [('vanilla', 4), ('chocolate', 1)]
Counter(responses).most_common(1)[0]
# ('vanilla', 4)
Counter(responses).most_common(1)[0][0]
# 'vanilla'
python -m http.server
会启动一个运行在8000端口的服务器,可以通过web浏览器访问:http://localhost:8000/
更改端口为5678
python -m http.server 5678