1. 面向对象中的常用方法 *****

isinstance() # 判断某个对象是不是某个类的实例

# 判断stu对象是不是Student类的实例

是不是子类
issubclass()
class Person:
pass
class Student(Person):
pass stu = Student() #判断 两个对象是不是同一个类型
print(type(1) == type(1)) # 判断stu对象是不是Student类的实例
print(isinstance(stu,Student)) # 是不是子类
# issubclass() # 判断一个类是不是 另一个类子类 (所有类都是object的子类或子子类)
print(issubclass(Student,Person)) print(isinstance(type,type)) 不仅能判断父类,还能判断父类的父类

2. 反射 *****

反射 其实说的是反省
简单的说就是对象具备一种修正错误的能力 hasattr 是否存在某个属性
getattr 获取某个属性的值
setattr 设置某个属性的值
delattr 删除某个属性 class Student:
def __init__(self,name,sex,age):
self.name = name
self.age = age
self.sex = sex def study(self):
print("学生正在学习...") stu = Student("矮根","woman",38) print(stu.name) stu.name = "高根"
print(stu.name) del stu.name
print(stu.name) # 当你获取到一个对象 但是并不清楚搞对象的内部细节时 就需要使用反射了
def test(obj):
if hasattr(obj,"name"):
print(getattr(obj,"name","没有name属性")) test(stu) setattr(stu,"school","beijing") delattr(stu,"school") print(getattr(stu,"school","没有学校属性")) delattr(stu,"age") print(stu.age) 这几个方法有一个共同点,都是通过字符串来操作属性
你可以理解为通过字符串来操作属性,就叫做属性 如果在编写代码期间 就能明确知道我要访问的属性 没有必要使用反射
如果在编写代码期间 无法明确知道我要访问的属性 这时就应该使用反射 # class Student:
# def study(self):
# print("学习中....") # stu = Student() # res = getattr(stu,"study",None) # print(res) # def eat(self):
# print("正在吃饭...") # # 可以通过反射的方式为对象增加一个方法 但是注意 这样增加的方法就是一个普通函数 不会自动传值
# setattr(stu,"eat",eat) # print(getattr(stu,"eat",None)) # 需要编写一个CMD工具 这个工具可以支持两个命令 dir ,tasklist class CMD: def dir(self):
print("列出当前文件夹目录....") def tasklist(self):
print("查看任务列表.....") cmd = CMD() res = input("请输入指令:").strip() if hasattr(cmd,res):
func = getattr(cmd,res)
print(func)
func()
else:
print("输入的指令不正确....")

str *****

__str__
前后带杠杠的都是特殊的内置函数,会在某些时机自动执行,一般情况我们不应该直接调用他们 当我们需要自定义打印显示内容时,就需要实现__str__方法
该方法返回一个字符串 返回的是什么,打印出来就是什么 class Test:
def __init__(self,name):
self.name = name
def __str__(self):
print("str run....")
return self.name
t = Test("安米") print(int(1).__str__())
# print([1,2,3,5].__str__())
print(t) # 在讲一个对象转换字符串时 本质就是在调用这个对象 __str__方法
print(str(t))

del ****

当对象被从内存中删除时,自动执行
另一种情况是,程序员手动删除了这个对象,也会自动执行 什么时候使用它
在python中有自动内存管理机制,所有python自己创建的数据,不需要我们做任何操作 但是有一种情况,我们使用python打开了一个不属于python管理的数据
比如打开了一个文件,这个文件一定是操作系统在打开 会占用系统内存 而python解释器无法操作系统内存的
所以 当你的python解释器运行结束后 文件依然处于打开状态 这时候就需要使用__del__来关闭系统资源 __del__也称之为析构函数
分析构造 并拆除这个对象 该方法其实就是一个通知性质,仅仅是告诉程序员,对象即将被删除
分析构造并拆除这个对象 class Student:
def __del__(self):
print("对象被删除了....") stu = Student() # 手动删除 立即执行__del__
del stu import time time.sleep(5) class TextFile: def __init__(self,filepath,mode="rt",encoding="utf-8"):
self.file = open(filepath,mode=mode,encoding=encoding) def read(self):
return self.file.read() def write(self,text):
self.file.write(text) # 该方法其实就是一个通知性质 仅仅是告诉程序员 对象即将被删除
def __del__(self):
# 在这里关闭系统的文件 妥妥的
self.file.close() tf = TextFile("2.今日内容.txt") print(tf.read()) # tf.file.close() # 不需要手动关闭了 在对象删除时会自动关闭 tf.read()

exec ****

execute的缩写
表示执行的意思 其作用 是帮你解析执行python代码 并且将得到的名称 存储到制定的名称空间 解释器内部也是调用它来执行代码的 参数一需要一个字符串对象,表示需要被执行的python语句
参数二是一个字典,会把字典放在全局名称空间中
参数三也是一个字典,会把字典放在局部名称空间中 exec('') globalsdic = {}
localsdic = {} exec("""
aaaaaaaaaaaaaaaaaaaa = 1
bbbbbbbbbbbbbbbbbbbbbbbbbbbb = 2
def func1():
print("我是func1")
""",globalsdic,localsdic) # 如果同时制定了 全局和局部 则 会字符串中包含名称 解析后存到局部中
# print(globalsdic)
print(localsdic)
localsdic["func1"]() 在字符串中定义好函数后,要用后面的字典名称去调用函数,直接在全局空间或者局部名称空间,用函数名调用会找不到

元类 ****

一切皆对象
元类是指用于产生类的类,type就是元类
所有的自定义类都是通过type实例化得来的
使用type可以发现,类其实是type类型的实例(对象) 创建模块的过程
1.创建一个空的名称空间
2.执行其内部的代码
3.将得到的名字放到名称空间中 # class也是一个对象
class Student(object): school = "北京大学!" def study(self):
print("学习中...") # 使用type可以发现 类其实是type类型的实例(对象)
print(type(Student)) 我们可以自己调用type来实例化产生一个类 # myclass 包含的代码
code = """
name = "张三"
age = 18
def hello(self):
print("hello %s" % self.name)
""" #类的名字
class_name = "MyClass"
#类的的父类们
base_classes = (object,)
#类的名称空间
namespace = {} exec(code,{},namespace) res = type(class_name,base_classes,namespace) print(Student)
print(res.name)
print(res.age)
print(res.hello) 1.类是由type实例化产生的
2.我们可以使用type来产生一个类
3.一个类由类名字,类的父类元组,类的名称空间三个部分组成 class Test(object): #就相当于Test = type("Test",(object,),{})
pass

自定义元类,元类也是一个类

def Person(metaclass = MyMeta)

call

调用的意思
在对象被调用(加括号时)时,执行 函数 类 自定义元类的目的
1.可以通过__call__来控制对象的创建过程
2.可以控制类的创建过程 class MyMeta(type):
def __call__(self,*args,**kwargs):
print('from Mymeta call run')
print(self,*args,*kwargs)
#下面三步是创建对象的固定写法,一个模板,只有你需要控制对象的创建过程,就必须先把模板写出来
obj = object.__new__(self)
self.__init__(obj,*args,**kwargs)
return obj class Person(metaclass=Mymeta):
def __init(self,name,age):
self.name = name
self.age = age
def __call__(self,*args,**kwargs):
print('Peson call run...') #调用Person这个对象时 执行的是 Person的类(type)中__call__ 方法
p = Person("张三疯",80) print(p)
# 当调用对象时 会执行该对象所属类中的__call__方法
p() print(p.name)
print(p.age) # 要控制类的创建过程 只要找到类所属的类 中的__init__即可
class MyMeta(type):
#要自己完成__init__函数完成类的创建
#self 表示要建出来的类
#第二个参数 类的名字
#第三个参数 类的父类们,元组形式
#第四个参数 这个类传进来的名称空间
def __init__(self,class_name,bases,namespace): # (在--init__中不实现赋值操作,python也会自动按位置传参)
print('==========')
#print(self.__dict__)
# 我要控制 类的名字 必须 是大写开头
if not class_name.istitle():
print("类名 必须大写开头...... ")
# 该代码是主动抛出异常
raise TypeError("类名 必须大写开头...... ")
if not self.__doc__:
raise TypeError('类中必须有中文档注释')
pass class Student(metaclass=MyMeta): # Student = MyMeta("student",(object,),{})
'''
这是文档注释,可以通过__doc__来获取
这是一个学生类
'''
# 在类的__init__中可以控制该类对象的创建过程
def __init__(self,name):
print('=======')
print(self.__dict__)
self.name = name print(Student.__doc__)

元类总结

元类是用于创建类的类
学习元类是为了能控制类的创建过程以及类实例化对象的过程 一.
控制类的创建过程
1.创建一个元类(需要继承type)
2.覆盖__init__方法 该方法 会将新建的类对象 类名 父类们 名称空间 都传进来,可以用这些信息再做处理
3.对于需要被控制的类 需要指定metaclass为上面的元类 二.
控制类实例化对象的过程
1.创建一个元类(需要继承type)
2.覆盖__call__方法 会将正在实例化对象的类,调用类时传入的参数,都传进来
3.在__call__方法中,必须要先编写模板代码
3.1创建空对象
3.2调用类的__init__方法来初始化这个空对象
3.3返回该对象 4.加入你需要控制的逻辑 类的三个组成部分
类名 父类名 名称空间 元类-> 实例化产生-> 类 -> 实例化产生 -> 对象

单例模式 ****

一种设计模式(套路)

单个实例
一个类如果只有一个实例,那么该类称为单例
为什么需要单例 class MyMeta(type):
obj = None
def __init__(self,*args,**kwargs):
if not MyMeta.obj:
obj = object.__new__(self)
self.__init__(obj,*args,**kwargs)
MyMeta.obj = obj
return MyMeta.obj
打印机类
class Printer(metaclass=MyMeta):
'''
这是一个单例类 请不要直接实例化,使用get方法来获取实例
'''
obj = None
def __init__(self,name,brand,type):
self.name = name
self.brand = brand
self.type = type
def printing(self,text):
print("正在打印 %s" % text) # 通过该方法来获取对象 可以保证只有一个对象
# 但是这还不够 因为 还是可以通过调用类产生新对象
# 就应该使用元类 来控制实例化的过程 __call__
# 在__call__ 中编写代码 保证每次调用call 都返回同一个实例 即可 @classmethod
def get_printer(cls):
if not cls.obj:
obj = cls("ES005","爱普生","彩色打印机")
cls.obj = obj
print("创建了新的对象") return cls.obj p = Printer.get_printer()
print(p) p = Printer.get_printer()
print(p) p = Printer.get_printer()
print(p) p = Printer.get_printer()
print(p) p1 = Printer("ES005","爱普生","彩色打印机")
p2 = Printer("ES005","爱普生","彩色打印机") print(p1)
print(p2)
# print(p1,p2,p3)
# p1.printing("一本小说....")

day26 面向对象的常用方法 和 元类的使用的更多相关文章

  1. 面向对象高级C(元类补充及单例模式)

    元类有关知识点补充 #类的名称空间 类的名称空间不能用类似字典的方法修改,例如School类里面有name属性xxx,那么我用School.__dict__['name'] = 'yyy'就会报错&q ...

  2. 面向对象高级B(元类)

    元类 python一切皆对象,类实际上也是一个一个对象 类是一个对象,那他一定是由一个类实例化得到,这个类就叫元类 如何找元类 class Person: def __init__(self, nam ...

  3. python中面向对象元类的自定义用法

    面向对象中的常用方法 1.instance 和 issubclass instance :判断两个对象是不是一类 issubclass :判断某个类是不是另一个类的子类 #两个常用方法的使用 clas ...

  4. Python面向对象篇之元类,附Django Model核心原理

    关于元类,我写过一篇,如果你只是了解元类,看下面这一篇就足够了. Python面向对象之类的方法和属性 本篇是深度解剖,如果你觉得元类用不到,呵呵,那是因为你不了解Django. 在Python中有一 ...

  5. Python全栈开发之9、面向对象、元类以及单例

    前面一系列博文讲解的都是面向过程的编程,如今是时候来一波面向对象的讲解了 一.简介 面向对象编程是一种编程方式,使用 “类” 和 “对象” 来实现,所以,面向对象编程其实就是对 “类” 和 “对象” ...

  6. python面向对象( item系列,__enter__ 和__exit__,__call__方法,元类)

    python面向对象进阶(下)   item系列 __slots__方法 __next__ 和 __iter__实现迭代器  析构函数 上下文管理协议 元类一.item系列 把对象操作属性模拟成字典的 ...

  7. 【转】python面向对象中的元类

    type() 动态语言和静态语言最大的不同,就是函数和类的定义,不是编译时定义的,而是运行时动态创建的. 比方说我们要定义一个Hello的class,就写一个hello.py模块: class Hel ...

  8. Python之面向对象元类

    Python之面向对象元类 call方法: class People: def __init__(self,name): self.name=name # def __call__(self, *ar ...

  9. 面向对象:元类、异常处理(try...except...)

    元类: python中一切皆对象,意味着: 1. 都可以被引用,如 x = obj 2. 都可以被当做函数的参数传入 3. 都可以被当做函数的返回值 4. 都可以当做容器类的元素(列表.字典.元祖.集 ...

随机推荐

  1. Maven下载私服上的jar包(全局)

    <mirror> <id>maven-public</id> <mirrorOf>maven-public</mirrorOf> <n ...

  2. 类库、委托、is/as

    一.类库(Class Library) 定义:类库是一个综合性的面向对象的可重用类型集合,这些类型包括:接口.抽象类和具体类.(内容不可见) 类库建立:文件--新建--项目--类库--生成解决方案 类 ...

  3. django之signal机制分析

    django的signal在djangobb中的使用: from django.db.models.signals import post_save from django.dispatch impo ...

  4. linux 组管理

    修改文件所有者 chown  用户名  文件名 修改文件所在的组 chgrp  组名    文件名 r = 4 , w = 2, x = 2 u  :所有者   g :所在组   o:其他组   a: ...

  5. 图文详解AO打印(端桥模式)(转)

    一.概述   AO打印是英文Active-Online Print的简称,也称主动在线打印.打印前支持AO通讯协议的AO打印机首先通过普通网络与C-Lodop服务保持在线链接,网页程序利用JavaSc ...

  6. 使用linux的shell脚本实现在当前行重复动态显示时间等字符串信息(不另起新行)

    ###本脚本在Suse11sp2当中验证正确 #!/bin/sh )) do echo -ne "\r$(date)" sleep 0.3 done ###关键在 echo 的 & ...

  7. 为什么java实体类需要重写toString方法

    如果没重写toString的情况: Object 类的 toString 方法 返回一个字符串,该字符串由类名(对象是该类的一个实例).at 标记符“@”和此对象哈希码的无符号十六进制表示组成.换句话 ...

  8. LeetCode OJ 215. Kth Largest Element in an Array

    Find the kth largest element in an unsorted array. Note that it is the kth largest element in the so ...

  9. python实现排序算法二:归并排序

    ##归并排序 ##基本思想:对于两个排好序的数组A和B,逐一比较A和B的元素,将较小值放入数组C中,当A或者B数组元素查询完后,将A或者B剩余的元素直接添加到C数组中,此时C数组即为有序数组,这就是归 ...

  10. 16.Set、List、Queue集合;Map.md

    目录 1.Set 1.2HashSet TreeSet 2.List 2.1ArrayList 2.1.1ArrayList和Vector的区别 2.2LinkedList 3.Queue 4.各种线 ...