基础
规范
1、PEP8
- 缩进与换行 每级缩进使用四个空格
- 限制每行的最大长度为 79 个字符
- 空行
- 顶层函数和类之间使用两个空行
- 类的方法之间用一个空行
- 在函数中使用空行表示不同逻辑段落
- 导入位于文件的顶部
- 避免多余空格
- 注释:注释要保持与时俱进,一句后面两个空格 跟注释
- 命名规范
- 除了正常的命名规范外
- 不要使用 大小写的 L 大写的 O 作为变量名
- 类名首字母大写 内部类 加上前导下划线
- 函数名应该小写 增强可读性可以使用下划线分割
- 其他
- 别用 == 进行布尔值 和 True 或者 False 的比较 应该用 is
2、注释
- 单行注释
# 我是单行注释
- 多行注释
"""
多行注释1
多行注释2
多行注释3
"""
- 类说明
class MiniOS:
"""miniOS 操作系统"""
... ...
- 函数说明
class APP:
def __init__(self, name, version, desc):
"""
这里指明这个函数的作用
:param name: str 软件名称
:param version: float 版本号
:param desc: str 文档说明
"""
3、命名风格
- 大驼峰:ClassName
- 小驼峰:className
- 下划线:parse_userinfo
- 私有化:__username
4、高内聚、低耦合
写代码要分模块,就像搭积木,一个功能一个模块,每个模块做好一件事,不同模块之间尽量不要互相依赖
- 内聚:一个函数中,各个元素彼此结合的紧密程度(单一责任原则)
- 耦合:各模块之间相互依赖的强弱
class Asd:
def a(self, v):
# return v + 1
return v + 2
def b(self, num):
return self.a(num) + 1
def c(self, num):
return self.b(num) + 3
def run(self):
# TODO: 除run()之外的函数,尽量避免耦合,达到低耦合的目的
# TODO:在这里完成高内聚
aa = self.a(num)
self.b(aa)
num = 100
AA = Asd()
print(AA.b(num))
print(AA.c(num))
5、编程思想
- POP(面向过程)
- OOP(面向对象):属性和行为的抽象封装
- SOA(面向服务架构)
- AOP(面向切面):提取过程中的切面,操作
业务逻辑中的某个步骤
==> 低耦合
6、SOLID
面向对象设计和编程中几个重要编码原则
- S 单一职责原则:一个类只负责一个功能领域中的相应职责
- O 开放/关闭原则:软件实体应开放对外扩展,而关闭修改
- L 里氏代换原则:所有引用基类对象的地方,能够透明化的使用其子类的对象
- I 接口隔离原则:使用多个专门的接口,而不使用但一个总接口
- D 依赖倒转原则: 抽象不应该依赖于细节,细节应该依赖于抽象
变量
- 公有变量
- 私有化:_,from xxx import yyy 时禁止导入
- 防止冲突/重载:__
- 魔法方法:__xx__
# 使用全局变量
# 注意:使用全局变量时候,修改变量的值 ==> 变量的数据类型
from comfig import SERVER_IP
# class Person(object):
class Person:
def __init__(self, name, age, sex):
sex =sdas
self.name = name
self._age = age
self.__sex = sex
导入
# 直接导入
from xxx import yyy
import xxx
# 导入多个
from xxx import *
import xxx, yyy
from xxx import yyy, zzz
# 取别名
# 修改导入的名称时,只需要在import后面改
import das
from xxx import yyy as Y
import sys
sys.path
# 依次查找列表中的包
['', # 首先查找当前路径
'/usr/bin',
... ....
]
# 可以通过append(),insert()方法向列表中添加
sys.path.append('/home/a/xxx')
sys.path.insert(0, '/home/a/xxx')
# import可以防止重复导入,就算导入5次,也只是第一次生效
import xx
# 重新导入 ==> 用来动态修改代码
from imp import reload
reload(xx)
环境
不同的项目,使用不同的包的版本
- virtualenv
workon NewVir
- pydev
cd ProjectName
- requirements.txt
pip freeze > requirements.txt
pip install -r requirements.txt
文档
- 需求文档
新式类
封装
- 调用
# def
from readfile import read_txt
content = read_txt(filename)
# class
from readfile import Read
content = Read.read_txt(filename)
from readfile.Read import read_txt
content = read_txt(filename)
- 变量
- 变量作用域
- 全局变量
- 局部变量
- 私有变量
- 变量作用域
- 隔离
@property
:让方法,像属性一样访问@staticmethod
:不使用形参__xx
:对外隐藏属性、方法
class Foo:
__x = 1 # _Foo__x = 1
def __f1(self): # _Foo__f1
print('from test')
def f2(self):
print(self.__x) # print(self._Foo__x)
print(self.__f1) # print(self._Foo__f1)
obj = Foo()
obj.f2()
print(Foo.__x)
print(Foo.__f1)
继承
- 多继承:
Python新式类MRO C3线性化算法
- MRO:方法搜索顺序
- 重写和重载
super()
class_name.__init__
方法会把每个父类全部执行一遍,而super()
,全部父类方法只执行一遍
- 由上可知,所有子类,统一
使用父类__init__中的参数
super(E, self)
还可以直接跳到E上面的类
,直接执行__init__方法MRO顺序如此,但是执行顺序是由我们的业务逻辑而定
class A:
def __init__(self):
print("A")
super(A, self).__init__()
class B(A):
def __init__(self):
print("B")
super(B, self).__init__()
class C(A):
def __init__(self):
print("C")
super(C, self).__init__()
class D(B, C):
def __init__(self):
print("D")
super(D, self).__init__()
D()
print(D.__mro__)
多态
class MiniOS:
"""miniOS 操作系统"""
def __init__(self, name):
self.name = name
self.apps = []
def __str__(self):
return f"{self.name} install_list: {str(self.apps)}"
def install_app(self, app):
# 判断是否已安装
if app.name in self.apps:
print(f"{app.name}已安装!")
else:
app.install()
self.apps.append(app.name)
class APP:
def __init__(self, name, version, desc):
self.name = name
self.version = version
self.desc = desc
def __str__(self):
return f"{self.name}: {self.version} {self.desc}"
def install(self):
print(f"正在安装{self.name}-{self.version}......")
class Pycharm(APP):
pass
class Chrome(APP):
def install(self):
print("解压缩安装!")
super(Chrome, self).install() # 重写父类方法
linux = MiniOS("Linux")
print(linux) # Linux install_list: []
pycharm = Pycharm("Pycharm", "1.0", "Pycharm IDE")
chrome = Chrome("Chrome", "1.1", "Chrome Install")
linux.install_app(pycharm) # 正在安装Pycharm-1.0......
linux.install_app(chrome) # 解压缩安装! ==> 正在安装Chrome-1.1......
linux.install_app(chrome) # Chrome已安装!
print(linux) # Linux install_list: ['Pycharm', 'Chrome']
设计模式
- 设计模式是经过总结、优化的,对我们经常会碰到的一些编程问题的可重用解决方案
- 是一种思想, 一种套路; 脱离编程语言
- 提高代码质量
单例模式
确保某一个类只有一个实例存在
class Singleton(object):
# 注意:先__new__创建一个实例对象,然后再__init__初始化实例对象
def __init__(self):
pass
def __new__(cls, *args, **kwargs):
if not hasattr(Singleton, "_instance"): # 反射
Singleton._instance = object.__new__(cls)
return Singleton._instance
obj1 = Singleton()
obj2 = Singleton()
print(obj1, obj2)
# <__main__.Singleton object at 0x004415F0> <__main__.Singleton object at 0x004415F0>
工厂模式
提供一个抽象化的接口来创建一个特定类型的对象,而不是决定哪个对象可以被创建
- 使用
- 不知道用户想要创建什么样的对象
- 当你想要创建一个可扩展的关联在创建类与支持创建对象的类之间
from abc import ABCMeta, abstractmethod
class Payment(metaclass=ABCMeta):
"""接口类"""
@abstractmethod
def pay(self, money):
pass
class Alipay(Payment):
def pay(self, money):
print(f"Alipay{money}")
class WechatPay(Payment):
def pay(self, money):
print(f"WechatPay{money}")
class PaymentFactory:
"""工厂类"""
def create_payment(self, method):
if method == "alipay":
return Alipay()
elif method == "wechat":
return WechatPay()
else:
raise TypeError(f"No such payment named {method}")
pay = Alipay()
pay.pay(12)
构造者模式
将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示
from abc import ABCMeta, abstractmethod
class Builder():
# 接口
__metaclass__ = ABCMeta
@abstractmethod
def draw_body(self):
pass
class Thin(Builder):
def draw_body(self):
print('画瘦身体')
class Fat(Builder):
def draw_body(self):
print('画胖身体')
class Director():
def __init__(self, person):
self.person = person
def draw(self):
self.person.draw_body()
if __name__ == '__main__':
# 将不同实例的引用传递到同一个构造类中,再调用不同实例的同名方法
thin = Thin()
director_thin = Director(thin)
director_thin.draw()
fat = Fat()
director_fat = Director(fat)
director_fat.draw()
适配器模式
- 使用
- 复用一些现存的类,但是接口又与复用环境要求不一致的情况
- 将一个类的接口转换成为客户希望的另外一个接口
class Target(object):
# 用户期望的类
def request(self):
print("普通请求")
class Adaptee(object):
# 需要适配的类
def specific_request(self):
print("特殊请求")
class Adapter(Target):
def __init__(self):
self.adaptee = Adaptee()
def request(self):
self.adaptee.specific_request()
if __name__ == "__main__":
# 在这里实例化的时候,实例化的是一个适配后的类
# 有一个用户期望的方法!
target = Adapter()
target.request()
装饰器模式
- 闭包:内层函数返回外层函数引用
- 装饰器:在不修改源码的情况下,增加一个额外的功能
- 语法糖:@,在某函数定义时,用以包装函数,以达到截取控制该函数的目的
评论区