【笔记】《Python语言以及应用》- 面向对象

一、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')

你可能感兴趣的:(【笔记】《Python语言以及应用》- 面向对象)