一、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
方法名 | 使用 |
---|---|
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) |
其它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')