day28 面向对象的进阶 反射 和类的内置方法

 一、上节回顾:

  #包

  #hashlib

    #登录验证,密文密码检测

      #密文cunc

      #加盐

      #动态加盐

    #检测文件一致性   MD5

      #MD5.update()

  #configparse:配置文件相关

    #网络变成 ftp

    #[section]

    #ol=yes

  #logging:日志

    #记录一些信息和结果

    #打日志

    #日志和print

    #学生管理系统

      #需要用户选择的时候打印提示信息

      #一个程序和用户发生文字交互的时候,不能使用logging

    #中间结果,错误提示么都可以使用logging

    #管理员在某时刻创建了一个班级————logging

二、今日内容:  

 (1)内置函数  ***

  (2)反射*****

  (3)类的内置双下方法 ***

  (4)面向对对象的高级代码和一道面试题

      #看书

      #看源码

      #看博客

        #简书

        #csdn

(一)内置函数

#property

#classmethod

#saticmethod

#super

#object

#isinstance

1、isinstance

    (对象,类)判断这个对象是不是这个类或者这个类的子类的实例化

from collections import Iterable
print(isinstance([],Iterable))  #True

class A:pass
class B(A):pass
b=B()
print(isinstance(b,A))  #True
print(isinstance(b,object))#True

2、issubclass

  (子类,类)判断一个类是否是另一个类的子类

class A:pass
class B(A):pass
print(issubclass(B,A))   #True
print(issubclass(A,B))  #False
print(issubclass(A,object))  #True
print(issubclass(B,object))  #True

3、补充:注释的添加

函数的注释添加

4、vars

# 看全局
# a=1
# b=2
# print(vars())
# print(dir())

class A:
    c=1
    d=2
    def func(self):
        self.name="alex"
# 看类
# print(vars(A))
a=A()
a.func()
# 看对象
print(vars(a))   #{'name': 'alex'}

(二)反射(非常重要)

对象的反射

类的反射

模块的反射

#hasattr()

#getattr()

#setattr()

#delattr()

python面向对象中的反射:通过字符串的形式操作相关的属性。python中一切事物的对象都可以使用反射

1、getattr(与eval的区别在于getattr不会存在的信息会报错,比较安全

class Management:
    role="管理员"
    def __init__(self,name,sex,phone,mail):
        self.name=name
        self.sex=sex
        self.phone=phone
        self.mail=mail
    def creat_class(self):
        print("创造了一个班级信息")
    def creat_teacher(self):
        print("创造了一个老师信息")
    def creat_student(self):
        print("创造了一个学生信息")
manager=Management("小鱼","",12331234567,"xiaoyu@qq.com")
func=input("func: ")
f=getattr(manager,func)
f()
getattr 管理信息的应用

解析:

  (1)方法名的调用

cs=getattr(manager,"creat_class")  使用字符串数据类型的方法名调用方法
cs()  #创造了一个班级信息

(2)属性的取用

#属性的的调用
f=getattr(manager,"phone")  #使用字符串数据类型的变量名获取属性值
print(f)  #12331234567

2、hasattr

(1)hasattr和getattr 组合调用

import logging
manager=Management("小鱼","",12331234567,"xiaoyu@qq.com")
if hasattr(manager,"sex1"):
    sex=getattr(manager,"sex1")   #使用字符串数据类型的变量名获取属性值
    print(sex)
else:
    logging.warning("没有您输入的属性")
#WARNING:root:没有您输入的属性

(2)类名的使用

if hasattr(Management,"role"):
    print(getattr(Management,"role")) #管理员

3、setattr  delattr(了解)字符串类型

# Management.Country="China"
setattr(Management,"Country","China")  #增加
print(Management.Country)  #China
# del Management.Country
delattr(Management,"Country")   #s删除
# print(Management.Country)

 (1)对象添加属性:

(2)使用delattr 删除一个类中的方法

delattr(Management,"creat_class")
manager.creat_class()

(3)绑定的方法(不常用)

def create_course(self):
    print("创建了一个课程")
setattr(manager,"create_course",create_course)
manager.create_course(manager)

总结:python的一切皆对象

 hasattr(类名(或者对象名),“属性名”)  返回True 或False

属性值=getattr(类名(或者对象名),“属性名”)

方法的内存地址=getattr(类名(或者对象名),“方法名”)

方法的内存地址()

(三)模块的反射

1、创建一个模块

2、调用模块中的属性

import demo
print(getattr(demo,"a"))
#1

3、调用模块中的函数

import demo
qq=getattr(demo,"qqxing") #调用函数名
qq("wahaha")   #给定一个参数
#qqxing: wahaha

4、接收模块中函数的返回值

import demo
qq=getattr(demo,"qqxing") #调用函数名
ret=qq("wahaha")   #给定一个参数
print(ret)    #接收函数的返回值
#qqxing: wahaha
# 大螃蟹

5、反射本模块的代码(核心是找到本模块sys.modules[__name__])

aaa="bbb"
import sys
print(sys.modules[__name__])
print(getattr(sys.modules[__name__],"aaa"))
#bbb

 解析:看有道截图

总结:

 

(四)类的内置方法

__str__和__repr__  改变对象的字符串显示

1、__str__方法

class A:
    pass
def __str__(self):
    return "A的对象"
a=A()
print(a)
print(a.__str__())
#打印一个对象的时候,实际上是调用了这个对象所在类的__str__方法,打印的是这个方法的返回值
print("%s"%a)

解析:

2、__repr__方法

(1)注释__repr__方法

class A:
    pass
    def __str__(self):
        return "A的对象"

    #def __repr__(self):
        #return "repr:A 的对象"
a=A()
print(a)
print(a.__str__())
print("%s"%a)
# A的对象
# A的对象
# A的对象

(2)注释__str__方法

class A:
    pass
    def __str__(self):
        return "A的对象"

    # def __repr__(self):
    #     return "repr:A 的对象"
a=A()
print(a)
print(a.__str__())
print(a.__repr__())
print("%s"%a)    #s=str
print("%r"%a)    #r=repr
print(str(a))
print(repr(a))
# A的对象
# A的对象
# <__main__.A object at 0x000000000220D630>
# A的对象
# <__main__.A object at 0x000000000220D630>
# A的对象
# <__main__.A object at 0x000000000220D630>

解析:

3、format(不重要)

格式化输出:

format_dict={
    "nat":"{obj.name}-{obj.addr}-{obj.type}",
    "tna":"{obj.type}:{obj.name}:{obj.addr}",
    "tan":"{obj.type}/{obj.addr}/{obj.name}"
}
class School:
    def __init__(self,name,addr,type):
        self.name=name
        self.addr=addr
        self.type=type
    def __format__(self, format_spec):
        if not format_spec or format_spec not in format_dict:
            format_spec="nat"
        fmt=format_dict[format_spec]
        return  fmt.format(obj=self)
s1=School("oldboy1","北京","私立")
print(format(s1,"nat"))
print(format(s1,"tna"))
print(format(s1,"tan"))
print(format(s1,"erasikfdhkasdffd"))
# oldboy1-北京-私立
# 私立:oldboy1:北京
# 私立/北京/oldboy1
# oldboy1-北京-私立
学校的例子
class School:
    def __init__(self,name,addr,type):
        self.name=name
        self.addr=addr
        self.type=type
    def __format__(self, format_spec):  # format_spec="nat"
        fmt="{obj.type}*{obj.addr}*{obj.name}"
        return  fmt.format(obj=self)
s1=School("oldboy1","北京","私立")
print(format(s1,"nat"))
# 私立*北京*oldboy1
学校的例子:第二种方法

解析:

大作业中的格式化输出:

 4、析构方法:

 

(1)主动删除(运行步骤从上往下)

class A:
    def __del__(self):
        print("执行我啦")
a=A()
del a
import time
time.sleep(2)
a=A()

(2)析构函数的应用场景,文件先关闭后删除

class A:
    def __del__(self):
        self.f.close()
        print("执行我啦")
f=open("file","w")
a=A()
a.f=f
del f
import time
time.sleep(2)

 总结:

5、item系列

 __getitem__\__setitem__\__delitem__

(1:访问的方式变了

  #对象名.属性

class Foo:
    def __init__(self,name):
        self.name=name
    def __getitem__(self, item):
        print(self.__dict__[item])
    def __setitem__(self, key, value):
        self.__dict__[key]=value
    def __delitem__(self, key):
        print('del obj[key]时,我执行')
        self.__dict__.pop(key)
    def __delattr__(self, item):
        print('del obj.key时,我执行')
        self.__dict__.pop(item)

f1=Foo("sb")
f1["age"]=18   #给f1添加一个属性
f1["age1"]=19
del f1.age1   #删除属性
del f1["age"]   #删除属性
f1["name"]="alex"
print(f1.__dict__)
# del obj.key时,我执行
# del obj[key]时,我执行
# {'name': 'alex'}
View Code

关于 item :对象访问,如果是对象名[],是因为内部实现了item系列的方法

6、__new__方法

面试的时候会用到

class Singleton:
    def __new__(cls, *args, **kwargs):
        if not hasattr(cls,"_instance"):
            cls._instance=object.__new__(cls)
        return cls._instance
    def __init__(self,name):
        self.name=name
one=Singleton("alex")
print(one.name)
two=one
two.name="agon"
View Code

 

7、__call__

class Foo:
    def __init__(self):
        pass
    def __call__(self, *args, **kwargs):
        print("__call__")

obj=Foo()  #执行__init__
obj() #执行__call__

obj=Foo()()  #对象后面加()就调用__call__
View Code

 8、__len__方法

class A:
    def __init__(self):
        self.a=1
        self.b=2
    def __len__(self):
        return len(self.__dict__)
a=A()
print(len(a)) #2
View Code

9、__hash__

class A:
    def __init__(self):
        self.a=1
        self.b=2
    def __hash__(self):
        return hash(str(self.a)+str(self.b))
a=A()
print(hash(a))
View Code

10、__eq__

class A:
    def __init__(self):
        self.a=1
        self.b=2
    def __eq__(self,obj):
        if self.a==obj.a and self.b==obj.b:
            return True
a=A()
b=A()
print(a==b)#True
View Code

 纸牌游戏

from collections import namedtuple
Card=namedtuple("Card",["rank","suit"])
c1=Card(2,"梅花")
class FranchDeck:
    ranks=[str(n) for n in range(2,11)]+list("JQKA")
    suits=["红心","方板","梅花","黑桃"]
    def __init__(self):
        self._cards=[Card(rank,suit) for rank in FranchDeck.ranks
                                                    for suit in FranchDeck.suits]

    def __len__(self):
        return len(self._cards)
    def __getitem__(self, item):
        return self._cards

deck=FranchDeck()
print(deck[0])
from random import choice
print(choice(deck))
print(c1.suit)
纸牌游戏

可以增加洗牌功能  随机抽牌功能

class FranchDeck:
    ranks = [str(n) for n in range(2,11)] + list('JQKA')
    suits = ['红心','方板','梅花','黑桃']

    def __init__(self):
        self._cards = [Card(rank,suit) for rank in FranchDeck.ranks
                                        for suit in FranchDeck.suits]

    def __len__(self):
        return len(self._cards)

    def __getitem__(self, item):
        return self._cards[item]

    def __setitem__(self, key, value):
        self._cards[key] = value

deck = FranchDeck()
print(deck[0])
from random import choice
print(choice(deck))
print(choice(deck))

from random import shuffle
shuffle(deck)
print(deck[:5])
纸牌游戏2

 面试题:

class Person:
    def __init__(self,name,age,sex):
        self.name = name
        self.age = age
        self.sex = sex

    def __hash__(self):
        return hash(self.name+self.sex)

    def __eq__(self, other):
        if self.name == other.name and self.sex == other.sex:return True


p_lst = []
for i in range(84):
    p_lst.append(Person('egon',i,'male'))

print(p_lst)
print(set(p_lst))
一道面试题

  

原文地址:https://www.cnblogs.com/number1994/p/8110446.html