面向对象之 —— isinstance、issubclass、反射、__str__、析构

一、isinstance\issubclass方法

isinstance(obj,cls):判断某个对象是不是某个类的实例

issubclass(sub,super):判断sub类是不是 super类子类/派生类 (所有类都是object的子类或子子类)

class Person:
    pass
class Student(Person):
    pass

stu = Student()

print(type(1) == type(1))  # True

print(isinstance(stu,Student))  # True

print(issubclass(Student,Person))  # True
举个栗子

 返回值都为bool类型

二、反射:对象具备修正错误的能力

程序可以访问、检测和修改它本身状态或行为的一种能力(自省),通过字符串来操作属性 

  • hasattr: (查看)是否存在某个属性
  • getattr: 获取某个属性的值
  • setattr: 设置某个属性的值
  • delattr: 删除某个属性
class BlackMedium:
    feature='Ugly'
    def __init__(self,name,addr):
        self.name=name
        self.addr=addr

    def sell_house(self):
        print('%s 黑中介卖房子啦' %self.name)
def rent_house(self): print('%s 黑中介租房子啦' %self.name) b1=BlackMedium('万成置地','回龙观天露园') #检测是否含有某属性 print(hasattr(b1,'name')) print(hasattr(b1,'sell_house')) #获取属性 n=getattr(b1,'name') print(n) func=getattr(b1,'rent_house') func() # getattr(b1,'aaaaaaaa') #报错 print(getattr(b1,'aaaaaaaa','不存在啊')) #设置属性 setattr(b1,'sb',True) setattr(b1,'show_name',lambda self:self.name+'sb') print(b1.__dict__) print(b1.show_name(b1)) #删除属性 delattr(b1,'addr') delattr(b1,'show_name') delattr(b1,'show_name111')#不存在,则报错 print(b1.__dict__)

 反射当前模块成员

#!/usr/bin/env python
# -*- coding:utf-8 -*-

import sys

def s1():
    print 's1'

def s2():
    print 's2'

this_module = sys.modules[__name__]
hasattr(this_module, 's1')
getattr(this_module, 's2')

需要编写一个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("输入的指令不正确....")

优点:可以事先定义好接口,接口只有在被完成后才会真正执行,即可以事先把主要逻辑写好(只定义接口),然后后期去实现接口的功能。可以动态导入模块(基于反射当前模块成员)

:前后带杠杠的都是特殊的内置函数(魔法方法),会在某些时机自动执行,一般情况我们不应该直接调用他们。要是实在想写一个同名的方法,可以写为_class模式(单下划线可防重名)。

三、__str__方法

当我们需要自定义打印显示内容时 就需要实现__str__方法,将对象转换成字符串时会自动执行,打印该对象时也会自动执行。
该方法必须返回一个字符串 返回的是什么 打印出来就是什么

class Test:
    def __init__(self,name):
        self.name = name
    def __str__(self):
        print("str run....")
        return self.name
t = Test("haha")

print(str(t))  # str run....     haha

改变对象的字符串显示:

  • __str__:不能在交互式环境显示
  • __repr__:交互模式在打印时其实是调用了__repe__,其输出结果面向的是解释器

自定制格式化字符串:__format__

 

四、__del__方法

解释器提醒即将把对象从内存中删除

将对象从内存中删除时会自动执行。程序员手动(调用__del__)删除这个对象也会自动执行

当使用python打开了一个不属于python管理的数据,因python解释器无法操作系统内存,故python解释器运行结束后,文件依然处于打开状态,此时就需要使用__del__关闭系统资源。简而言之,就是在程序运行结束时进行清理操作(如关闭文件资源)。

__del__也称之为析构函数,即分析构造,并拆除这个对象

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 执行字符串类型的python代码,用于执行文档内部程序

exec(execute):执行,解析执行字符串类型的python代码,并且将得到的名称存储到指定的名称空间,解释器内部也是调用它来执行代码的

# 参数一 需要一个字符串对象 表示需要被执行的python语句
# 参数二 是一个字典 表示全局名称空间
# 参数三 也是一个字典 表示局部名称空间(通常都是局部)

globalsdic = {}
localsdic = {}

exec("""
aaaaaaaaaaa = 1
bbbbbbbbbbb = 2
def func1():
    print("func1")
""",globalsdic,localsdic)

# 如果同时制定全局和局部 则会将字符串中包含的名称 解析后存到局部中
# print(globalsdic)
print(localsdic)
localsdic["func1"]()
# 如果只传了一个传参数 则将字符串中包含名称 解析后存到全局中
 

典型的应用场景:

创建数据库类,用该类实例化出数据库链接对象,对象本身是存放于用户空间内存中,而链接则是由操作系统管理的,存放于内核空间内存中。

当程序结束时,python只会回收自己的内存空间,即用户态内存,而操作系统的资源则没有被回收,这就需要我们定制__del__,在对象被删除前向操作系统发起关闭数据库链接的系统调用,回收资源。这与文件处理是一个道理。

f=open('a.txt') #做了两件事,在用户空间拿到一个f变量,在操作系统内核空间打开一个文件
del f #只回收用户空间的f,操作系统的文件还处于打开状态

#所以我们应该在del f之前保证f.close()执行,即便是没有del,程序执行完毕也会自动del清理资源,于是文件操作的正确用法应该是
f=open('a.txt')
读写...
f.close()
很多情况下大家都容易忽略f.close,这就用到了with上下文管理
文件处理

 

posted @ 2019-05-29 21:01  呔!妖精。。。  阅读(142)  评论(0编辑  收藏  举报