day 017面向对象-反射

 主要内容:

  •  isinstance, type, issubclass( 内置函数)
  • 区分函数和方法
  • 反射

一    ( isinstance, type, issubclass)

  1.    isinstance()  :可以帮我们判断xx类是否是xx类的子类.       
class Basse:
    pass
class Foo:
    pass
lass Bar(Foo): pass print(issubclass(Bar,Foo)) #true print(issubclass(Foo,Bar)) #false print(issubclass(Bar,Basse)) # False

       2. type() : 表示查看obj是由哪个类创建的

class Foo:
    pass
obj = Foo()
print( obj,type(obj)) # 查看obj的类 <__main__.Foo object at 0x0000019D93228198> <class '__main__.Foo'>
判断好要计算的数据类型必须是int或者float

def add(a, b):
if (type(a) == int or type(a) == float) and (type(b) == int or type(b) == float): return a + b else: print("我要报错")

      3. isinstance() : 也可以判断xxx是YY类型的数据.但是它没有type那么精准.

lass Animal:
    pass

class Cat(Animal):
    pass

class BoSiCat(Cat):
    pass

# a = Animal()
# print(isinstance(a, Animal)) # 自己类可以判断
# print(isinstance(a, Cat))   # 子类不能判断

c = BoSiCat()
print(isinstance(c, Animal)) # True  子类的对象可以当成父类的类型来看.

isinstance 可以判断对象是否是xxx家族体系中的(只能往上判断)

二   区分函数和方法

我们可以直接用打印来看结果

例子

class Foo:
    def chi(self):
        print("我是吃")
    @staticmethod
    def static_method():
        pass
    @classmethod
    def class_method(cls):
        pass
f=Foo()
print(f.chi) #  <bound method Foo.chi of <__main__.Foo object at 0x0000023453028588>>
 print(Foo.chi)  #<function Foo.chi at 0x000001AFE215A950
print(f.static_method) #  拿对象来访问function Foo.static_method at 0x0000022A951AA9D8>
print(Foo.static_method) #   拿类来访问<function Foo.static_method at 0x0000014459E4A9D8>
print(f.class_method)  #<bound method Foo.class_method of <class '__main__.Foo'>>
print(Foo.class_method)  #那类来访问 <bound method Foo.class_method of <class '__main__.Foo'>>

结论:  类方法: 无论任何情况都是方法

          静态方法:无论任何情况都是函数

          实例方法: 如果是实力访问就是方法,如果是类名访问就是函数

 那如何用程序来帮我们分辨到底是函数换是方法呢? 

例子:

首先我们要借助typrs模块

# 所有的方法都是Method的实例
#所有的函数都是functiontypes的实例

from types import MethodType,FunctionType  #引入模块
def func():
    pass
print(isinstance(func,FunctionType)) #true
print(isinstance(func,MethodType)) # false
class Foo:
    def chi(self):
        print("我是吃")
    @staticmethod
    def static_method():
        pass
    @classmethod
    def class_method(cls):
        pass
obj=Foo()
print()
print(type(obj.chi)) # method
print(type(Foo.chi)) # function

# print(isinstance(obj.chi, MethodType)) # True
# print(isinstance(Foo.chi, FunctionType)) # True
#
# print(isinstance(Foo.static_method, FunctionType)) # True
# print(isinstance(Foo.static_method, MethodType)) # False
#
# print(isinstance(Foo.class_method, FunctionType)) # False
# print(isinstance(Foo.class_method, MethodType)) #true

三 反射 

import fanshe  # 引入模块
from types import FunctionType

# while 1:
#     print('''大牛写的功能
#     chi
#     he
#     la
#     shui
#     调试哪个''')
#     ts=input("请输入你要调试的功能")
#     if ts=='chi':
#          fanshe.chi()
#     elif ts=="he":
#         fanshe.he()
#     elif ts=="la":
#         fanshe.la()
#     elif ts=='shui':
#         fanshe.shui()
#     else:
#         print("大牛没有这个功能")
#写是写完了. 但是.....如果大牛现在写了了100个功能呢? 你的判断要判断100次么?
# 我们可以使用反射来完成这样的功能. 非常的简单. 想想. 这里我们是不是让用户输入要执行的功能了. 那这个功能就是对应
# 模块里的功能. 那也就是说. 如果能通过字符串来动态访问模块中的功能就能解决这个问题

#例子2
# while 1:
#     print('''大牛写的功能
#     chi
#     he
#     la
#     shui
#     调试哪个''')
#     ts=input("请输入你要调试的功能")
#     func=getattr(fanshe,ts)  # geattr (对象,字符串)从对象中获取到xxx功能,此时xxx表示一个字符串,get
#                                 #表示找,attr表示属性功能
#     func()

 ## 写完了 但是这样有个问题在大牛的代码里没有你要找的内容,这时侯就会报错,所以在获取attr之前,要先判断下
 #有没有这个功能
 # 看下完整代码:
# while 1:
#     print('''大牛写的功能
#       chi
#       he
#       la
#       shui
#       调试哪个''')
#     ts = input("请输入你要调试的功能")
#     if getattr(fanshe, ts):  #如果fanshe里有你要的功能
#           # 获取这个功能,并执行
#         attr=getattr(fanshe,ts)
#         if isinstance(attr,FunctionType): #判断是否是函数,只有函数才可以被调用
#             attr()
#         else:     #如果不是就打印
#             print(attr)

#  两个函数 getattr():来获取信息 从对象中获取xxx功能
#             hasattr()用来判断xxx中是否包含了xxx功能
# class person:
#     cuontry="daqing"
#     def chi(self):
#         pass
#
# # 类中的内容可以这样动态的进⾏行行获取
# print(getattr(person, "country"))
# print(getattr(person, "chi"))  # 相当于Foo.func 函数
# # 对象⼀一样可以
# obj = person()
# print(getattr(obj, "country"))
# print(getattr(obj, "chi"))  # 相当于obj.func ⽅方法
  # 总结 getattr可以从模块中获取也可以从类中获取,也可以从类中获取.在python中一切皆对象
  # 那可以这样认为.getattr从对象中动态获取成员.
  #来看个例子:
class person:
    def cih(self):
        print("")
    def he(self):
        print("")
    def la(self):
        print("")
    def sa(self):
        print("sa")
    def shui(self):
        print("")
    def run(self):
        lst=['chi','he','la','sa','shui']
        num = int(input("""本系统有以下功能
        1. 吃
        2. 喝喝
        3. 拉
        4. 撒
        5. 睡
        请选择你要执⾏行行的功能:"""))
    # func = getattr(Person, lst[num - 1])
    # func(self)
    # 通过对象来访问更更加合理理
    # method = getattr(self, lst[num-1])
    # method()
p=person()
p.run()


# 补充:
# 关于反射, 其实一共有4个函数:
# 1. hasattr(obj, str) 判断obj中是否包含str成员
# 2. getattr(obj,str) 从obj中获取str成员
# 3. setattr(obj, str, value) 把obj中的str成员设置成value. 注意. 这⾥里里的value可以是
# 值, 也可以是函数或者⽅方法
# 4. delattr(obj, str) 把obj中的str成员删除掉
# 注意, 以上操作都是在内存中进行的. 并不会影响你的源代码



#setarrt 例子1
# class Foo:
#     pass
# f = Foo()
# print(hasattr(f, "chi")) # False
#
# setattr(f, "chi", "123")
# print(f.chi) # 被添加了了⼀一个属性信息
#
# setattr(f, "chi", lambda x: x + 1)
# print(f.chi(3)) # 4

## setarrt 例子2

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

    def chi(self):
        print("人喜欢吃东西%s" % self.name)

p = Person("刘伟")
setattr(p, "name", "大阳哥") # 动态的给对象设置属性和值
setattr(p, "age", 18) # 很少用. 慎用

print(p.age)
delattr(p, "age")
print(p.age)

# p.chi()

# val = input("请输入你想让刘伟执行的动作:")
# if hasattr(p, val):
#     getattr(p, "name")
#     func = getattr(p, val)
#     func()

猜你喜欢

转载自www.cnblogs.com/systemsystem/p/9720425.html