面向对象的进阶(三) ~懒得起名了


issubclass/type/isinstance、函数和方法、反射、callable、特殊成员补充
 

一、issubclass/type/isinstance(***)

  1、issubclass(参数1, 参数2):检查第一个参数是否是第二个参数的 子子孙孙类,如下示例:

class Base(object):
        pass

    class Foo(Base):
        pass

    class Bar(Foo):
        pass

    print(issubclass(Bar, Foo)) # True
    print(issubclass(Bar, Base)) # True

2、type():获取当前对象时由哪个类创建,如下示例:

# #####示例一:判断一个参数是不是某一个指定类的对象
    class Foo(object):
        pass

    obj = Foo()
    print(obj,type(obj)) 
    # <__main__.Foo object at 0x0000000002618F60> <class '__main__.Foo'>
    if type(obj) == Foo: # 判断一个参数是不是某一个指定类的对象
        print('obj是Foo类型')

    # #####示例二:练习题:判断函数的参数分别是哪个类的对象
    class Foo(object):
        pass

    class Bar(object):
        pass

    def func(*args):
        foo_counter = 0
        bar_counter = 0
        for item in args:
            if type(item) == Foo:
                foo_counter += 1
            elif type(item) == Bar:
                bar_counter += 1
        return foo_counter, bar_counter

    print(func(Foo(), Bar(), Foo()))  # (2, 1)

# 补充:示例三:如何判断参数是不是一个类
class Foo(object):
pass
obj = Foo()
print(type(Foo) == type) # True
print(type(obj) == type) # False

 

3、isinstance(参数1, 参数2):检查第一个参数是否是第二个参数的实例,如下示例:

# #####示例一:判断一个参数是不是某一个指定类或其父类的对象
    class Base:
        pass
    class Foo(Base):
        pass
    class Bar(Foo):
        pass
    obj1 = Bar()
    print(isinstance(obj1, Bar))  # True
    print(isinstance(obj1, Foo))  # True
    print(isinstance(obj1, Base))  # True

    obj2 = Foo()
    print(isinstance(obj2, Bar))  # False

二、用科学的方式判断是函数和方法(*)

  一般我们笼统的称定义在类中的函数为方法,定义在类外的就是函数,其实是不太严谨的,如下示例:

# #####示例一:如何看得出是函数还是方法
    def func():
        pass
    class Foo(object):
        def inner(self):
            pass
        @staticmethod
        def detail():
            pass
    print(func)  # <function func at 0x00000000028C99D8>  是函数

    obj = Foo()
    print(obj.inner)  # 是方法
    # <bound method Foo.inner of <__main__.Foo object at     0x00000000028D1208>> 
    print(Foo.detail)  # <function Foo.detail at     0x00000000028F9AE8>  是函数
    print(obj.detail)  # <function Foo.detail at 0x00000000028F9AE8>  是函数

如何看得出是函数还是方法
如何看的出是函数还是方法

其实,在python中,一切皆对象,只要是对象,它就有对应的类,函数是FunctionType创建的,方法是由MethodType创建的,所以,我们可以按照如下示例判断是函数还是方法:

# #####示例二
    from types import MethodType,FunctionType
    def check(arg):
        """
        检查arg是方法还是函数?
        """
        if isinstance(arg,MethodType):
            print('arg是一个方法')
        elif isinstance(arg,FunctionType):
            print('arg是一个函数')
        else:
            print('不知道是什么')
    check(func)  # arg是一个函数
    check(obj.inner)  # arg是一个方法
# #####示例三:是不是方法跟写在哪里没关系,跟调用有关系
    class Foo(object):
        def f1(self):
            pass

    obj = Foo()
    obj.f1()    # 把f1当做方法,python自动传self值
    print(obj.f1)
    # <bound method Foo.f1 of <__main__.Foo object at 0x0000000002724390>>
    obj = Foo()
    Foo.f1(obj) # 把f1当做函数,需要自己传参数
    print(Foo.f1)  # <function Foo.f1 at 0x0000000002791AE8>

是不是方法跟写在哪里没有关系,跟调用有关系
是不是方法跟写在哪里没关系,跟调用有关系
# #####示例四:练习题
    class Foo(object):
        def f1(self):
            pass
        def f2(self):
            pass
        def f3(self):
            pass
        list_display = [f1,f2]
        def __init__(self):
            pass
    for item in Foo.list_display:
        print(item)
        item(123)  # item是函数,所以要自己传参数
    # 结果为:
    # <function Foo.f1 at 0x00000000029A3B70>
    # <function Foo.f2 at 0x00000000029A3BF8>

练习题一
练习题
# #####示例五
    class Foo(object):
        def f1(self):
            pass
        def f2(self):
            pass
        def f3(self):
            pass
        list_display = [f1,f2]

    obj = Foo()
    Foo.list_display.append(obj.f3)

    for item in Foo.list_display:
        print(item)
    # 结果为:
    # <function Foo.f1 at 0x0000000002973D90>
    # <function Foo.f2 at 0x0000000002973E18>
    # <bound method Foo.f3 of <__main__.Foo object at 0x0000000002908A90>>

练习题二
练习题2

 总结:执行那个类里边的  .什么功能  的时候,如果是 对象.功能,那么这个功能就是方法。

    对象.xxx  --- >  xxx就是方法

    类.xxx    --- >  xxx就是函数

三、反射(*****)

  重点:v = getattr(obj , “func”)  # 根据字符串为参数(第二个参数),去对象(第一个参数)中寻找与之同名的成员。

应用一、首先定义一个handler模块,handler.py文件内容如下:

f0 = 9
    def f1():
        print('F1')
    def f2():
        print('F2')
    def f3():
        print('F3')
    def f4():
        print('F4')
    def f5():
        print('F5')

handler.py
handler.py

学习了反射,我们可以这样写,如下示例:

from types import FunctionType
    import handler
    while True:
        print("""
        系统支持的函数有:
            1. f1
            2. f2
            3. f3
            4. f4
            5. f5
        """)
        val = input("请输入要执行的函数:")  

        if hasattr(handler, val):  # 假如  val = "f1"
            func_or_val = getattr(handler, val)  
            # 根据字符串为参数,去模块中寻找与之同名的成员。
            if isinstance(func_or_val, FunctionType):
                func_or_val()  # 是函数则执行
            else:
                print(func_or_val)  # 不是函数则打印出来
        else:
            print('handler中不存在输入的属性名')

应用二、用户登录、注销、注册程序:

class Account(object):
        func_list = ['login', 'logout', 'register']
        def login(self):
            """
            登录
            """
            print('登录111')
        def logout(self):
            """
            注销
            """
            print('注销111')
        def register(self):
            """
            注册
            """
            print('注册111')
        def run(self):
            """
            主代码
            """
            print("""
                请输入要执行的功能:
                    1. 登录
                    2. 注销
                    3. 注册
            """)
            choice = int(input('请输入要执行的序号:'))
            func_name = Account.func_list[choice-1]

            func = getattr(self, func_name)  # self.login
            func()

    obj1 = Account()
    obj1.run()

反射补充:还是以引入handler模块为例:

import handler
    # hasattr
    v1 = hasattr(handler,'f0')
    v2 = hasattr(handler,'f1')
    v3 = hasattr(handler,'f2')
    v4 = hasattr(handler,'xxx')
    print(v1,v2,v3,v4)  # True True True False

    # setattr
    setattr(handler,'x2',999)
    v5 = getattr(handler,'x2')
    print(v5)  # 999

    setattr(handler,'f8',lambda x:x+1)
    v6 = getattr(handler,'f8')
    v7 = v6(1)
    print(v7)  # 2

    # delattr
    delattr(handler,'f0')
    # v8 = getattr(handler,'f0')
    # print(v8) # AttributeError: module 'handler' has no attribute 'f0'

总结:

  getattr   # 根据字符串的形式,去对象中找成员;

  hasattr   # 根据字符串的形式,去判断对象中是否有成员;

  setattr   # 根据字符串的形式,动态的设置一个成员(内存);

  delattr   # 根据字符串的形式,动态的删除一个成员(内存);

四、补充知识点(callable)

  你见过的什么后面可以加括号?

    -  类()             -  对象()

    -  函数()           -  方法()

  以上所有都可以被调用。如何验证呢?如下示例:

def func():
        pass

    class Foo(object):
        def __call__(self, *args, **kwargs):
            pass
        def func(self):
            pass
    obj = Foo()
    print(callable(func))  # True
    print(callable(Foo))  # True
    print(callable(obj))  # True
    print(callable(obj.func))  # True

五、特殊成员补充

# print(对象),会自动执行__str__方法
    class Foo(object):
        def __init__(self):
            pass
        def func(self):
            pass
        def __str__(self):
            return "F1"  # 必须返回字符串
    obj = Foo()
    print(obj,type(obj))  # F1 <class '__main__.Foo'>

__str__
__str__
# __doc__
    class Foo(object):
        """
        这里是注释
        """
        def __init__(self):
            pass
        def func(self):
            pass
        def __str__(self):
            return "F1"

    obj = Foo()
    print(obj.__doc__) # 这里是注释

__doc__
__doc__
# __dict__
    class Foo(object):
        def __init__(self, name, age):
            self.name = name
            self.age = age
        def func(self):
            pass
    obj1 = Foo('刘博文', 99)
    obj2 = Foo('史雷', 89)
    print(obj1.__dict__)  # {'name': '刘博文', 'age': 99}
    print(obj2.__dict__)  # {'name': '史雷', 'age': 89}

__dict__
__dict__
# __iter__
    class Foo(object):
        def __init__(self,name,age):
            self.name = name
            self.age = age
        def __iter__(self):
            return iter([11,22,33])
            # 生成器
            # yield 11
            # yield 22
            # yield 33
    """
    如果想要把不可迭代对象 -> 可迭代对象
    1. 在类中定义__iter__方法
    2. iter内部返回一个迭代器(生成器也是一种特殊迭代器)
    """
    obj1 = Foo('刘博文',99)
    for item in obj1:
        print(item)
    # 结果为:
    # 11
    # 22
    # 33

__iter__
__iter__
原文地址:https://www.cnblogs.com/wxj1129549016/p/9563818.html