Python自学Day17-18 函数的使用方式与面向对象

函数的使用方式

将函数视为“一等公民”

  • 函数可以赋值给变量
  • 函数可以作为函数的参数
  • 函数可以作为函数的返回值

高阶函数的用法(filter、map以及它们的替代品)

位置参数、可变参数、关键字参数、命名关键字参数

参数的元信息(代码可读性问题)

匿名函数和内联函数的用法(lambda函数)

闭包和作用域问题

  • Python搜索变量的LEGB顺序(Local –> Embedded –> Global –> Built-in)
  • global和nonlocal关键字的作用
    • global:声明或定义全局变量(要么直接使用现有的全局作用域的变量,要么定义一个变量放到全局作用域)。
    • nonlocal:声明使用嵌套作用域的变量(嵌套作用域必须存在该变量,否则报错)。

装饰器函数(使用装饰器和取消装饰器)

例子:输出函数执行时间的装饰器。

如果装饰器不希望跟print函数耦合,可以编写带参数的装饰器。

例子:用装饰器来实现单例模式。

面向对象相关知识

三大支柱:封装、继承、多态

例子:工资结算系统。

类与类之间的关系

  • is-a关系:继承
  • has-a关系:关联 / 聚合 / 合成
  • use-a关系:依赖

例子:扑克游戏。

对象的复制(深复制/深拷贝/深度克隆和浅复制/浅拷贝/影子克隆)

垃圾回收、循环引用和弱引用

Python使用了自动化内存管理,这种管理机制以引用计数为基础,同时也引入了标记-清除和分代收集两种机制为辅的策略。

导致引用计数+1的情况:

  • 对象被创建,例如a = 23
  • 对象被引用,例如b = a
  • 对象被作为参数,传入到一个函数中,例如f(a)
  • 对象作为一个元素,存储在容器中,例如list1 = [a, a]

导致引用计数-1的情况:

  • 对象的别名被显式销毁,例如del a
  • 对象的别名被赋予新的对象,例如a = 24
  • 一个对象离开它的作用域,例如f函数执行完毕时,f函数中的局部变量(全局变量不会)
  • 对象所在的容器被销毁,或从容器中删除对象

引用计数可能会导致循环引用问题,而循环引用会导致内存泄露,如下面的代码所示。为了解决这个问题,Python中引入了“标记-清除”和“分代收集”。在创建一个对象的时候,对象被放在第一代中,如果在第一代的垃圾检查中对象存活了下来,该对象就会被放到第二代中,同理在第二代的垃圾检查中对象存活下来,该对象就会被放到第三代中。

# 循环引用会导致内存泄露 - Python除了引用技术还引入了标记清理和分代回收

# 在Python 3.6以前如果重写__del__魔术方法会导致循环引用处理失效

# 如果不想造成循环引用可以使用弱引用

list1 = []

list2 = []

list1.append(list2)

list2.append(list1)

以下情况会导致垃圾回收:

  • 调用gc.collect()
  • gc模块的计数器达到阀值
  • 程序退出

如果循环引用中两个对象都定义了__del__方法,gc模块不会销毁这些不可达对象,因为gc模块不知道应该先调用哪个对象的__del__方法,这个问题在Python 3.6中得到了解决。

也可以通过weakref模块构造弱引用的方式来解决循环引用的问题。

魔法属性和方法(请参考《Python魔法方法指南》)

有几个小问题请大家思考:

  • 自定义的对象能不能使用运算符做运算?
  • 自定义的对象能不能放到set中?能去重吗?
  • 自定义的对象能不能作为dict的键?
  • 自定义的对象能不能使用上下文语法?

混入(Mixin)

例子:自定义字典限制只有在指定的key不存在时才能在字典中设置键值对。

元编程和元类

例子:用元类实现单例模式。

面向对象设计原则

  • 单一职责原则 (SRP)- 一个类只做该做的事情(类的设计要高内聚)
  • 开闭原则 (OCP)- 软件实体应该对扩展开发对修改关闭
  • 依赖倒转原则(DIP)- 面向抽象编程(在弱类型语言中已经被弱化)
  • 里氏替换原则(LSP) – 任何时候可以用子类对象替换掉父类对象
  • 接口隔离原则(ISP)- 接口要小而专不要大而全(Python中没有接口的概念)
  • 合成聚合复用原则(CARP) – 优先使用强关联关系而不是继承关系复用代码
  • 最少知识原则(迪米特法则,LoD)- 不要给没有必然联系的对象发消息
  • 说明:上面加粗的字母放在一起称为面向对象的SOLID原则。

GoF设计模式

  • 创建型模式:单例、工厂、建造者、原型
  • 结构型模式:适配器、门面(外观)、代理
  • 行为型模式:迭代器、观察者、状态、策略

例子:可插拔的哈希算法。

 

本文来自这个系列长期转载Python-100-Days ,本文观点不代表蓝洛水深立场,转载请联系原作者。

(0)
蓝洛水深的头像蓝洛水深管理员
上一篇 2019年11月27日 下午10:56
下一篇 2019年11月30日 上午12:17

相关推荐

发表回复

登录后才能评论
联系QQ