目录
一、面向对象三大特性之封装
1.封装简介:
封装:就是将数据和功能封装起来,封装是一种概念
baike封装,即隐藏对象的属性和实现细节,仅对外公开接口,控制在程序中属性的读和修改的访问级别;将抽象得到的数据和行为(或功能)相结合,形成一个有机的整体,也就是将[数据]与操作数据的[源代码]进行有机的结合,形成“类”
2.隐藏
隐藏:隐藏对象的属性和实现细节,仅对外公开接口,控制在程序中属性的读和修改的访问级别(在接口内添加额外的操作)
类在定义阶段,名字前面加两个下划线,那么该名字会被隐藏起来,无法直接访问
class MyClass:
__name = 'duo'
def __func(self):
pass
# 属性和方法名字前面加双下__也可以隐藏
3.伪装
伪装:将类中的方法伪装成属性,可以用点号运算符来调用,被修饰符@property修饰的函数
(1)只有 @property
表示 只读 。
(2)同时有 @property
和@*.setter
表示 可读可写 。
(3)同时有 @property
和 @*.setter
和@*.deleter
表示可读可写可删除。
二、面向对象三大特性之多态
1.多态的含义
多态:一种事物的多种形态
面向对象的多态:拥有相同功能的类,这些类的功能应该被命名为同一个方法名
2.抽象与多态
多态的实际操作:抽象
由于类 Cat 中有talk方法,而其他和Cat相同类别的类,也可以有talk方法,所以可以将talk方法抽象出来,让Cat和具有相同功能的类去继承这个基类Animal,这个时候我们可以说Animal是抽象基类。
import abc
# 指定metaclass属性将类设置为抽象类,抽象类本身只是用来约束子类的,不能被实例化
class Animal(metaclass=abc.ABCMeta):
@abc.abstractmethod # 该装饰器限制子类必须定义有一个名为talk的方法
def talk(self): # 抽象方法中无需实现具体的功能
pass
class Cat(Animal): # 但凡继承Animal的子类都必须遵循Animal规定的标准
def talk(self):
pass
cat = Cat() # 若子类中没有一个名为talk的方法则会抛出异常TypeError,无法实例化
三、面向对象之反射
反射:introsepction自省的一种方式,利用字符串操作对象的数据和方法,
主要用于和对象交互
1. hasattr:判断一个方法是否存在与这个类中
2. getattr:根据字符串去获取obj对象里的对应的方法的内存地址,加"()"括号即可执行
3. setattr:通过setattr将外部的一个函数绑定到实例中
4. delattr:删除一个实例或者类中的方法
1.hasattr(object, name)
返回布尔值,判断某个属性或者方法是否在这个对象中
2.getattr(object, name)
拿到对象中名字所对应的值并返回,如果没有则报错
3.setattr(object, name, value)
根据字符串给对象设置或者修改数据
4.delattr(object, name)
根据字符串删除对象里面的名字
四、面向对象之魔法方法
(1)__init__
对象实例化的时候自动触发
(2)__str__
对象被执行打印(print、前端展示)操作的时候自动触发,方法必须返回字符串类型的数据,很多时候用来更加精准的描述对象(通过str方法可以区分打印的是哪个对象)
(3)__call__
对象加括号调用的时候自动触发,当类中没有__call__
的时候该类产生的对象不可调用
(4)__getattr__
对象查找不存在名字的时候自动触发
(5)__getattribute__
只要对象查找名字无论名字是否存在都会执行该方法,如果类中有__getattribute__
方法 那么就不会去执行__getattr__
方法
(6)__setattr__
对象在执行添加属性操作的时候自动触发 >>> obj.变量名=变量值
(7)__enter__
当对象被当做with上下文管理操作的开始自动触发,并且该方法返回什么 as后面的变量名就会接收到什么
(8)__exit__
对象被执行with上下文管理语法结束之后自动触发
(9)__del__
对象被执行(被动、主动)删除操作之后自动执行
(10)__new__
__new__
方法来产生的一个空对象
五、元类
1.元类简介
我们定义的类其实都是有type类产生的>>>type类被称为元类,类本身不过是一个名为 type 类的实例
2.元类的用法
(1)元类定制类的行为:创建类的两种方法
1)使用关键字class
class MyClass:
pass
print(MyClass)
print(MyClass.__dict__)
-------------结果-------------
<class '__main__.MyClass'>
2)利用元类type
元类初始化实例的参数为**:type(类名what, 类的父类bases,类的名称空间dict)
# 则可以用变量名来接收元类type初始化实例后的结果,其结果就是一个type元类产生的类
cls = type('Student', (object,), {})
print(cls)
print(cls.__dict__)
-----------结果--------------
<class '__main__.Student'>
{'__module__': '__main__', '__dict__': <attribute '__dict__' of 'Student' objects>, '__weakref__': <attribute '__weakref__' of 'Student' objects>, '__doc__': None}
# 通过type也可以产生类,并且cls的名称空间中也具有和关键字class所产生的类一样的名字
(2)元类定制类的产生行为
1.自定义元类:继承了type到类也称之为元类
class MyMetaClass(type):
def __init__(self, what, bases=None, dict=None):
"""what是类名,bases是父类,dict是名称空间"""
if not what.istitle():
raise TypeError('类名首字母应该大写')
super().__init__(what, bases, dict)
2.指定类的元类:利用关键值metaclass指定类的元类
class myclass(metaclass=MyMetaClass): # TypeError: 类名首字母应该大写 当首字母没有大写当时候,则会报错
desc = '你好'
class Myclass(metaclass=MyMetaClass): # 类名首字母大写则不会报错
desc = '你好'
(3)元类定制对象的产生行为
class MyMetaClass(type):
def __call__(self, *args, **kwargs):
if args:
raise TypeError('无法位置传参')
return super().__call__(*args, **kwargs) # __call__的值必须返回才能获得
class Student(metaclass=MyMetaClass):
def __init__(self, name, age, hobby):
print('init')
self.name = name
self.age = age
self.hobby = hobby
obj = Student(name='duoduo', age=18, hobby='read')
print(obj.__dict__) # {'name': 'duoduo', 'age': 18, 'hobby': 'read'}
六、设计模式之单例模式
设计模式:前人通过大量的验证,所创建出来的解决一些问题的固定高效方法
单例模式:确保一个类最多只有一个实例,在整个程序就使用一个对象,可以节省内存空间
1.基于模块的单例
提前产生一个对象,之后导模块使用
class C1:
def __init__(self, name):
self.name = name
obj = C1('duoduo')
"""
在其他py文件中,去导入该obj,
由于导入模块只发生一次,那么在该文件中
那么这些对象的id()是一样的
"""
2.装饰器@classmethod实现单例模式
class C1:
__instance = None
def __init__(self, host, port):
self.host = host
self.port = port
@classmethod
def singleton(cls):
if not cls.__instance:
cls.__instance = cls('duoduo', [])
return cls.__instance
obj1 = C1.singleton()
obj2 = C1.singleton()
obj3 = C1.singleton()
# 此时obj1、obj2、obj3的id地址都是一样的
七、pickle序列化模块
pickle能够序列化python中所有类型的数据,但是只限制于python中使用。一般用于将一个对象序列化到文件中保存,这样用pickle读取出来还是这样一个对象。
pickle读取或者写入的时候,都只能用二进制模式。
import pickle
# 写入
with open(r'a.txt', 'wb') as f:
pickle.dump(obj, f)
# 读取
with open(r'a.txt', 'rb') as f:
res = pickle.load(f)
print(res) # <__main__.C1 object at 0x10454bdc0>
标签:__,name,对象,self,11.7,11.11,元类,小结,class
From: https://www.cnblogs.com/DuoDuosg/p/16890318.html