分分钟钟学会Python - 面向对象
目录
面向对象
1 三大特性
-
面向对象基本格式
# 定义 class 类名:# 类名首字母大写 def 方法名(self,name):# self不用传参,name必须传参 print(name) return 123 def 方法名(self,name): print(name) return 456 # 调用类的方法 1.创建类的对象 # 实例化 obj = 类名() 2.通过对象调用方法 result = obj.方法名('dpsy') # 使用对象调用类的方法 print(result) # 返回值
-
对象的作用
存储一些值,以后方便自己使用
-
将数据封装到对象,方便使用
class file: def read(self): with open(self.wenjian,mode="r",encoding='utf-8') as f: data = f.read() return data def write(self,content): with open(self.wenjian,mode='a',encoding='utf-8') as f: f.write(content) # 实例化一个file的对象 obj2 = file() # 在对象中写一个wenjian = "test.txt" obj2.wenjian = "info.txt" # 通过对象调用类中的read方法,read方法中的self就是obj.read() obj2.write("dpsy")
组合:一个类的对象作为另一个类对象的实例变量
-
继承
什么时候用继承? 多个类中如果有公共的方法,可以放到基类中避免重复编写
self 到底是谁?
self 是哪个类创建的,就从此类开始找,自己(子类、派生类)没有就找父类(基类,超类)。
-
多继承就从左往右找,左面找到跟,在找右面
- 深度优先
- 广度优先
-
新式类和经典类
py2继承object就是新式类;默认经典类
py3都是新式类,默认继承object
-
新式类
- 继承object
- 支持super
- 多继承 广度优先c3算法
- mro方法
-
经典类
- py2中不继承object
- 没有super语法
- 多继承 深度优先
- 没有mro方法
class a: pass # def func(self): # print('a') class b(a): pass # def func(self): # print('b') class c(a): def func(self): print('c') class d(b,c): pass # def func(self): # print('d') d = d() d.func() print(d.mro()) # dbca # dbac
-
多态(多种形态/多种类型) 鸭子模型
# python def func(arg): v = arg[-1] # arg.append(9) print(v) # java def func(str arg): v = arg[-1] print(v)
-
总结
-
面向对象的三大特性:封装/继承/多态
-
封装
class file: def read(self): pass def write(self): pass class person: def __init__(sef,name,age): self.name = name self.age = age p = person('alex',19)
-
继承
class base: pass class foo(base): pass
-
多态
def func(arg): # 多种类型,很多事物 arg.send() # 必须具有send方法,呱呱叫
-
-
格式和关键词
class 类: def __init__(self,x): self.x = x def 方法(self,name): print(self.x, name) # 实例化一个类的对象 v1 = 类(666) v2.方法('alex')
关键词
- 类
- 对象
- 方法
-
什么时候用面向对象?
- 函数(业务功能)比较多,可以使用面向对象来进行归类。
- 想要做数据封装(创建字典存储数据时,面向对象)。
- 游戏示例:创建一些角色并且根据角色需要再创建人物。
-
2 类成员
- 类
- 类变量
- 绑定方法
- 类方法
- 静态方法
- 属性
- 实例(对象)
- 实例变量
实例变量
-
类变量
定义:写在类的下一级和方法同一级
所有方法都能共享且唯一
-
使用
- 类.类变量名称
- 对象.类变量名称
总结:找变量优先找自己,自己没有找类或基类,修改或赋值只能在自己的内部设置
-
方法(绑定方法或普通方法)
定义:至少有一个self参数
-
执行:先创建对象,有对象.方法()
class foo: def func(self,a,b): print(a,b) obj = foo() obj.func(1,2) class foo: def __init__(self): self.name = 123 def func(self,a,b) print(self.name,a,b) obj = foo() obj.func(1,2)
-
静态方法
-
定义:
- @staticmethod装饰器
- 参数无限制
-
执行:
- 类.静态方法名()
- 对象.静态方法名()(不推荐)
-
-
类方法
-
定义:
- @classmethod装饰器
- 至少有cls参数,当前类
-
执行:
- 类.类方法()
- 对象.类方法() (不推荐)
-
-
属性
- 定义:
- @property装饰器
- 只有一个self参数
- 执行:
- 对象.方法 不需要加括号
class foo: @property def func(self): print(123) return 33 obj = foo() result = obj.func print(result)
- 定义:
3 成员修饰符
公有,所有地方都能访问到
私有,只有自己可以访问到
-
补充 类的嵌套
class foo: pass class foo(object): pass # 在python3中这俩的写法是一样,因为所有的类默认都会继承object类,全部都是新式类。 # 如果在python2中这样定义,则称其为:经典类 class foo: pass # 如果在python2中这样定义,则称其为:新式类 class foo(object): pass class base(object): pass class bar(base): pass
-
强制访问私有实例变量
class foo: def __init__(self,name): self.__x = name obj = foo('alex') print(obj._foo__x) # 强制访问私有实例变量
4 特殊成员
作用: 就是能够快速实现执行某些方法而生
-
__init__
初始化方法class foo: """ 类是干啥的 """ def __init__(self,a1) """ 初始化方法 """ self.a1 = a1 obj = foo('alex')
-
__new__
用于创建空的对象,构造方法class foo(object): def __init__(self): """ 用于给对象中赋值,初始化方法 """ seif.a = 123 def __new__(cls,*args,**kwargs): """ 用于创建空的对象,构造方法 """ return object.__new__(cls) obj = foo()
-
__call__
对象加括号可以直接执行class foo(object): def __call__(self,*args,**kwargs); print('执行call方法') # 执行方式一 obj = foo obj()* # 执行方式二 foo()()
-
__getitem__
用于索引操作,如字典。表示 获取 数据__setitme__
用于索引操作,如字典。表示 设置 数据__delitem__
用于索引操作,如字典。表示 删除 数据class foo(object): def __setitem__(self, key, value): pass def __getitem__(self, item): return item + 'uuu' def __delitem__(self, key): pass obj1 = foo() obj1['k1'] = 123 # 内部会自动调用 __setitem__方法 val = obj1['xxx'] # 内部会自动调用 __getitem__方法 print(val) del obj1['ttt'] # 内部会自动调用 __delitem__ 方法
-
__str__
只有在print对象时,会自动化调用此方法class foo(object): def __str__(self): """ 只有在打印对象时,会自动化调用此方法,并将其返回值在页面显示出来 :return: """ return 'asdfasudfasdfsad' obj = foo() print(obj) # asdfasudfasdfsad
-
__dict__
去对象中找到所有变量并将其转换为字典class foo(object): def __init__(self,name,age,email) self.name = name self.age = age self.email = email obj = foo('dpsy',23,921921921@qq.com) val = obj.__dict__ print(val) # {'name': 'dpsy', 'age': 23, 'email': '921921921@qq.com'}
-
上下文管理
class foo(object): def do_something(self): print('内部执行') class context: def __enter__(self): print('进入') return foo() def __exit__(self, exc_type, exc_val, exc_tb): print('推出') with context() as ctx: print('内部执行') ctx.do_something() # 读写文件 class foo(object): def __enter__(self): self.x = open('a.txt',mode='a',encoding='utf-8') return self.x def __exit__(self, exc_type, exc_val, exc_tb): self.x.close() with foo() as ff: ff.write('dpsy')
-
两个对象相加
val = 5 + 8 print(val) val = "大王八" + "一万年" print(val) class foo(object): def __add__(self, other): return 123 obj1 = foo() obj2 = foo() val = obj1 + obj2 print(val)
5 栈
-
代码从上到下执行
类可以做类的方法
-
栈:后进先出
队列:先进后出
# class queue(object): # 队列 class stack(object): # 栈 """ 后进先出 """ def __init__(self): self.data_list = [] def push(self,val): """ 入栈:向栈中压入一个数据 :param val: :return: """ self.data_list.append(val) def pop(self): """ 出栈:从栈中拿走一个数据 :return: """ return self.data_list.pop()
6 约束(抽象类/接口类)
-
约束子类中必须写父类中指定的方法,如果不写,则调用时候就报notimplementederror
class interface(object): def send(self): raise notimplementederror("子类中没有send") class message(interface): def send(self): print("发送短信") class email(interface): print(123) obj = message() obj1 = email() # 123 obj.send() # 发送短信 obj1.send() # notimplementederror: 子类中没有send
7 反射
根据字符串的形式去某个对象中操作他的成员
通过 对象 来获取 实例变量、绑定方法
通过 类 来获取 类变量、类方法、静态方法
通过 模块名 来获取 模块中的任意变量(普通变量 函数 类)
通过 本文件 来获取 本文件中的任意变量
# getattr(sys.modules[name],'变量名')
-
getatter(对象,"字符串") 根据字符串的形式去某个对象中获取对象的成员
class foo(object): def __init__(self,name): self.name = name def login(self): print(123) obj = foo('sd') # 获取变量 v1 = getattr(obj,'name') print(v1) # 获取方法 method_name = getattr(obj,'login') method_name()
-
hasattr(对象,"字符串") 根据字符串的形式去某个对象中判断是否有该成员,如果对象有该属性返回 true,否则返回 false。
class foo: a = 1 b = 2 obj = foo() print(hasattr(obj,'a')) print(hasattr(obj,'b'))
-
satattr(对象,'变量','值') 根据字符串的形式去某个对象中设置成员
class foo: k1 = 1 obj = foo() setattr(obj,'k1',123) # 相当于obj.k1 = 123 print(obj.k1)
-
delattr(对象,'变量') 根据字符串的形式去某个对象中删除成员
class foo: k1 = 1 obj = foo() delattr(obj,'k1') print(obj.k1)
-
python一切皆对象,所以以后想要通过字符串的形式操作其内部成员都可以通过反射的机制实现。
- py文件
- 包
- 类
- 对象
8 单例模式
-
无论实例化多少次,永远用的都是第一次实例化出的对象
class foo: pass # 多例,每实例化一次就创建一个新的对象。 obj1 = foo() # 实例,对象 obj2 = foo() # 实例,对象 # 单例,无论实例化多少次,都用第一次创建的那个对象。 obj1 = foo() obj2 = foo()
-
单例的标准
class singleton(object): instance = none def __new__(cls, *args, **kwargs): if not cls.instance: cls.instance = object.__new__(cls) return cls.instance obj1 = singleton() obj2 = singleton() # 不是最终,加锁。
-
文件的连接池
class filehelper(object): instance = none def __init__(self, path): self.file_object = open(path,mode='r',encoding='utf-8') def __new__(cls, *args, **kwargs): if not cls.instance: cls.instance = object.__new__(cls) return cls.instance obj1 = filehelper('x') obj2 = filehelper('x')
-
通过模块导入的特性也可以实现单列模式
# jd.py 自定义模块 class foo(object): pass obj = foo()
# app.py 导入模块 import jd # 加载jd.py,加载最后会实例化一个foo对象并赋值给obj print(jd.obj)