zoukankan      html  css  js  c++  java
  • 面向对象 --- 进阶篇

      类的成员                                                                        

    类的成员可以分为三大类 : 字段 , 方法和属性

      类成员 :   

          字段 : 普通字段    静态字段

          方法 : 普通方法    静态方法      类方法

          属性 : 普通属性

      注 : 所有成员中 , 只有普通字段的内容保存对象中 , 即 : 根据此类创建了多少对象 , 在内存中就有多少个普通字段 . 而其他的成员 , 则都是保存在类中 , 即 : 无论对象的多少 , 在内存中只创建一个 .

    一 . 变量

      变量包括 : 实例变量(字段)和类变量(静态字段)

        * 实例变量(字段)属于对象

        * 类变量(静态字段)属于类

    class Province:
    
        # 静态字段
        country = '中国'
    
        def __init__(self, name):
    
            # 普通字段
            self.name = name
    
    
    # 直接访问普通字段
    obj = Province('河北省')
    print obj.name
    
    # 直接访问静态字段
    Province.country
    
    字段的定义和使用
    普通和静态的区别

      由上述代码可以看出[普通字段需要通过对象来访问]  [静态字段通过类访问]

        * 静态字段在内存中只保存一份

        * 普通字段在每个对象中都要保存一份

    class Foo:
        # 类变量(静态字段)
        country = "中国"
                                
        def __init__(self,name):
            # 实例变量(字段)
            self.name = name  
                                
                                
        def func(self):
            pass
                    
                    
    obj1 = Foo('小桃红')
    obj2 = Foo('何润东')
                            
    Foo.country
    公有实例变量
    # 无法访问 :
    class Base(object):
        __secret = "受贿"
    
    class Foo(Base):
    
        def func(self):
            print(self.__secret)
            print(Foo.__secret)
    
    
    obj = Foo()
    obj.func()
    
    
    # 可以访问
    class Base(object):
        __secret = "受贿"
    
        def zt(self):
            print(Base.__secret)
    
    
    class Foo(Base):
    
        def func(self):
            print(self.__secret)
            print(Foo.__secret)
    
    
    obj = Foo()
    obj.zt()
    私有实例变量

    二 . 方法

      方法包括 : 普通方法 , 静态方法和类方法 , 三种方法在内存中都归属类 , 区别在于调用方式不同 . 

        * 实例方法 : 由对象调用 ; 至少一个self参数 ; 执行普通方法时 , 自动将调用该方法的对象赋值给self ;

    class Foo(object):
        def __init__(self, name):
            self.name = name
    
        # 实例方法
        def func(self):
            print(self.name)
                                    
    obj = Foo('..')
    obj.func()
    实例

        * 类方法 : 由类调用 ; 至少一个cls参数 ; 执行类方法时 , 自动将调用该方法的类复制给cls ;

    class Foo(object):
    
        def __init__(self, name):
            self.name = name
    
        # 静态方法,如果方法无需使用对象中封装的值,那么就可以使用静态方法
        @staticmethod
        def display(a1,a2):
            return a1 + a2
    
    Foo.display(1,3)
    实例

        * 静态方法 : 由类调用 ; 无默认参数;

    class Foo(object):
                            
        # 类方法,cls是类
        @classmethod
        def show(cls,x1,x2):
            print(cls,x1,x2)
    
    # 执行类方法
    Foo.show(1,8)
    实例
    class Foo:
    
        def __init__(self, name):
            self.name = name
    
        def ord_func(self):
            """ 定义普通方法,至少有一个self参数 """
    
            # print self.name
            print '普通方法'
    
        @classmethod
        def class_func(cls):
            """ 定义类方法,至少有一个cls参数 """
    
            print '类方法'
    
        @staticmethod
        def static_func():
            """ 定义静态方法 ,无默认参数"""
    
            print '静态方法'
    
    
    # 调用普通方法
    f = Foo()
    f.ord_func()
    
    # 调用类方法
    Foo.class_func()
    
    # 调用静态方法
    Foo.static_func()
    
    方法的定义和使用
    方法和定义

      相同点 : 对于所有的方法而言 , 均属于类中 , 所以 , 在内存也只保存一份 .

      不同点 : 方法调用者不同 , 调用方法时自动传入的参数不同 .

    三 . 属性

      属性就是实例方法的变种 .

      属性的知识点 :

        * 属性的基本使用

        * 实现的两种定义方式

      1 . 属性的基本使用

    # ############### 定义 ###############
    class Foo:
    
        def func(self):
            pass
    
        # 定义属性
        @property
        def prop(self):
            pass
    
    # ############### 调用 ###############
    foo_obj = Foo()
    
    foo_obj.func()
    foo_obj.prop   #调用属性
    属性的定义和使用

      由属性的定义和调用要注意以下几点 :

        * 定义时 , 在普通方法的基础上面添加 @property 装饰器 ;

        * 定义时 , 属性仅有一个 self 参数

        * 调用时 , 无需括号

              方法 : foo_obj.func()

              属性 : foo_obj.prop

      注意 : 属性存在意义是 : 访问属性时可以制造出和访问字段完全相同的假象

           属性由方法变种而来 , 如果Python中没有属性 , 方法完全可以代替其功能 .

    # 根据用户请求的当前页和总数据条数计算出 m 和 n
    # 根据m 和 n 去数据库中请求数据 
    
    # ############### 定义 ###############
    class Pager:
        
        def __init__(self, current_page):
            # 用户当前请求的页码(第一页、第二页...)
            self.current_page = current_page
            # 每页默认显示10条数据
            self.per_items = 10 
    
    
        @property
        def start(self):
            val = (self.current_page - 1) * self.per_items
            return val
    
        @property
        def end(self):
            val = self.current_page * self.per_items
            return val
    
    # ############### 调用 ###############
    
    p = Pager(1)
    # p.start 就是起始值,即:m
    # p.end   就是结束值,即:n

      由上述可见 , Python的属性的功能是 : 属性内部进行一系列的逻辑计算 , 最终将计算结果返回

      2 . 属性的两种定义方式

        属性的定义有两种方式 : 

          装饰器 即 : 在方法上应用装饰器

          静态字段 即 : 在类中定义值为property对象的静态字段

      装饰器方式 : 在类的普通方法上应用@property装饰器

        经典类 : 

    # ############### 定义 ###############    
    class Goods:
    
        @property
        def price(self):
            return "wupeiqi"
    # ############### 调用 ###############
    obj = Goods()
    result = obj.price  # 自动执行 @property 修饰的 price 方法,并获取方法的返回值
    经典类

        新式类 :

    # ############### 定义 ###############
    class Goods(object):
    
        @property
        def price(self):
            print '@property'
    
        @price.setter
        def price(self, value):
            print '@price.setter'
    
        @price.deleter
        def price(self):
            print '@price.deleter'
    
    # ############### 调用 ###############
    obj = Goods()
    
    obj.price          # 自动执行 @property 修饰的 price 方法,并获取方法的返回值
    
    obj.price = 123    # 自动执行 @price.setter 修饰的 price 方法,并将  123 赋值给方法的参数
    
    del obj.price      # 自动执行 @price.deleter 修饰的 price 方法
    新式类

      注:经典类中的属性只有一种访问方式,其对应被 @property 修饰的方法
             新式类中的属性有三种访问方式,并分别对应了三个被@property、@方法名.setter、@方法名.deleter修饰的方法

      由于新式类中具有三种访问方式,我们可以根据他们几个属性的访问特点,分别将三个方法定义为对同一个属性:获取、修改、删除

    class Goods(object):
    
        def __init__(self):
            # 原价
            self.original_price = 100
            # 折扣
            self.discount = 0.8
    
        @property
        def price(self):
            # 实际价格 = 原价 * 折扣
            new_price = self.original_price * self.discount
            return new_price
    
        @price.setter
        def price(self, value):
            self.original_price = value
    
        @price.deltter
        def price(self, value):
            del self.original_price
    
    obj = Goods()
    obj.price         # 获取商品价格
    obj.price = 200   # 修改商品原价
    del obj.price     # 删除商品原价
    
    实例
    实例

      静态字段方式 ,创建之为property对象的静态字段

        当使用静态字段的方式创建属性时 , 经典类和新式类无区别

        property的构造方法中有四个参数:

          1 . 方法名 , 调用 对象.属性 时自动触发执行方法

          2 . 方法名 , 调用 对象.属性 = xxx 时自动触发执行方法

          3 . 方法名 , 调用 del 对象.属性 时自动触发执行方法.

          4 . 字符串 , 调用 对象.属性.__doc__ ,次参数是该属性的描述信息

    class Foo:
    
        def get_bar(self):
            return 'wupeiqi'
    
        # *必须两个参数
        def set_bar(self, value): 
            return return 'set value' + value
    
        def del_bar(self):
            return 'wupeiqi'
    
        BAR = property(get_bar, set_bar, del_bar, 'description...')
    
    obj = Foo()
    
    obj.BAR              # 自动调用第一个参数中定义的方法:get_bar
    obj.BAR = "alex"     # 自动调用第二个参数中定义的方法:set_bar方法,并将“alex”当作参数传入
    del Foo.BAR          # 自动调用第三个参数中定义的方法:del_bar方法
    obj.BAE.__doc__      # 自动获取第四个参数中设置的值:description...
    View Code

     类成员的修饰符                                                             

      对于每一个类的成员而言都有两种形式 : 

        * 公有成员 , 在任何地方都能访问

        * 私有成员 , 只有在类的内部才能访问

    class C:
     
        def __init__(self):
            self.name = '公有字段'
            self.__foo = "私有字段"
    

        静态字段

    • 公有静态字段:类可以访问;类内部可以访问;派生类中可以访问
    • 私有静态字段:仅类内部可以访问;
      class C:
      
          name = "公有静态字段"
      
          def func(self):
              print C.name
      
      class D(C):
      
          def show(self):
              print C.name
      
      
      C.name         # 类访问
      
      obj = C()
      obj.func()     # 类内部可以访问
      
      obj_son = D()
      obj_son.show() # 派生类中可以访问
      
      公有静态字段
      公有
      class C:
      
          __name = "私有静态字段"
      
          def func(self):
              print C.__name
      
      class D(C):
      
          def show(self):
              print C.__name
      
      
      C.__name       # 类访问            ==> 错误
      
      obj = C()
      obj.func()     # 类内部可以访问     ==> 正确
      
      obj_son = D()
      obj_son.show() # 派生类中可以访问   ==> 错误
      
      私有静态字段
      私有

      普通字段

    •     公有普通字段:对象可以访问;类内部可以访问;派生类中可以访问
    •     私有普通字段:仅类内部可以访问;
      class C:
          
          def __init__(self):
              self.foo = "公有字段"
      
          def func(self):
              print self.foo  # 类内部访问
      
      class D(C):
          
          def show(self):
              print self.foo # 派生类中访问
      
      obj = C()
      
      obj.foo     # 通过对象访问
      obj.func()  # 类内部访问
      
      obj_son = D();
      obj_son.show()  # 派生类中访问
      
      公有字段
      公有
      class C:
          
          def __init__(self):
              self.__foo = "私有字段"
      
          def func(self):
              print self.foo  # 类内部访问
      
      class D(C):
          
          def show(self):
              print self.foo # 派生类中访问
      
      obj = C()
      
      obj.__foo     # 通过对象访问    ==> 错误
      obj.func()  # 类内部访问        ==> 正确
      
      obj_son = D();
      obj_son.show()  # 派生类中访问  ==> 错误
      
      私有字段
      私有

        私有成员只能在类内部使用

     类的组合                                                                          

      类或对象可以做字典中的key和value的

    lass Foo:
        pass
    
    user_info = {
        Foo:1,
        Foo():5
    }
    
    print(user_info)
    View Code

      让我们看一看对象中到底有什么?

    class StarkConfig(object):
    
        def __init__(self,num):
            self.num = num
    
        def changelist(self,request):
            print(self.num,request)
    
    class RoleConfig(StarkConfig):
    
        def changelist(self,request):
            print('666')
    
    # 创建了一个列表,列表中有三个对象(实例)
    # [ StarkConfig对象(num=1), StarkConfig对象(num=2), RoleConfig对象(num=3) ]
    config_obj_list = [StarkConfig(1),StarkConfig(2),RoleConfig(3)]
    for item in config_obj_list:
        print(item.num)
    
    # 结果
    # 1
    # 2
    # 3
    View Code
    class UserInfo(object):
        pass
    
    class Department(object):
        pass
    
    class StarkConfig(object):
    
        def __init__(self,num):
            self.num = num
    
        def changelist(self,request):
            print(self.num,request)
    
        def run(self):
            self.changelist(999)
    
    class RoleConfig(StarkConfig):
    
        def changelist(self,request):
            print(666,self.num)
    
    class AdminSite(object):
        def __init__(self):
            self._registry = {}
    
        def register(self,k,v):
            self._registry[k] = v(k)
    
    site = AdminSite()
    site.register(UserInfo,StarkConfig)
    site.register(Department,StarkConfig)
    print(len(site._registry)) # 3
    for k,row in site._registry.items():
        row.run()
    实例

      总结 : 

        1. 对象中封装了什么?

        2. self到底是谁?

      只有明白这两个问题,就不会错

    # ############# 创建学校 ##########
    class School:
        def __init__(self, address):
            self.address = address
    
    bj = School('北京校区')
    sh = School('上海校区')
    sz = School('深圳校区')
    
    # ################ 创建课程 ##########
    class Course(object):
        def __init__(self, name, period, price, school=None):
            self.name = name
            self.period = period
            self.price = price
            self.school = school
    # ########## 学校和课程的组合 #########
    py1 = Course('Python全栈', 110, 19999, bj)
    py2 = Course('Python全栈', 110, 19999, sh)
    py3 = Course('Python全栈', 110, 19999, sz)
    
    l1 = Course('Linux运维', 110, 19999, bj)
    l2 = Course('Linux运维', 110, 19999, sh)
    
    g1 = Course('Go开发', 119, 19999, bj)
    
    
    class Grade(object):
        def __init__(self, name, people, introduce, course=None):
            self.name = name
            self.people = people
            self.introduce = introduce
            self.course = course
            
    # ######### 班级和课程的组合 #########
    # 北京
    gr1 = Grade('11期',20,'....',py1)
    gr2 = Grade('15期',20,'....',py1)
    
    gr3 = Grade('11期',20,'....',l1)
    gr4 = Grade('12期',20,'....',l1)
    
    gr5 = Grade('21期',20,'....',g1)
    gr6 = Grade('65期',20,'....',g1)
    # 上海
    gr7 = Grade('1期',20,'....',l2)
    gr8 = Grade('2期',20,'....',l2)
    
    gr9 = Grade('1期',20,'....',py2)
    gr10 = Grade('2期',20,'....',py2)
    # 深圳
    gr11 = Grade('1期',20,'....',py3)
    
    # 查看哪个学校哪个课程哪个班级人数
    print(gr1.people)
    # 查看哪个学校哪个课程的学费
    print(gr1.course.price)
    # 查看哪个课程哪个班级在哪个学校
    print(gr1.course.school.address)
    组合的实例

      1 . 主动调用其他类的成员

    class Base(object):
    
        def f1(self):
            print('5个功能')
    
    class Foo(object):
    
        def f1(self):
            print('3个功能')
        
            Base.f1(self)        #调用别的类
    
    obj = Foo()
    obj.f1()            
    方式一
    class Foo(object):
        def f1(self):
            super().f1()     #按照类的继承顺序找下一个
            print('3个功能')
    
    class Bar(object):
        def f1(self):
            print('6个功能')
    
    class Info(Foo,Bar):
        pass
    
    
    
    obj = Info()
    obj.f1()
    
    # 结果:
    '''
    6个功能
    3个功能
    '''
    方式二

     类的特殊成员                                                                   

           上文介绍了Python的类成员以及成员修饰符,从而了解到类中有字段、方法和属性三大类成员,并且成员名前如果有两个下划线,则表示该成员是私有成员,私有成员只能由类内部调用。无论人或事物往往都有不按套路出牌的情况,Python的类成员也是如此,存在着一些具有特殊含义的成员,详情如下:

      1. __init__

        初始化方法 , 对空对象初始化 , [类名()]   自动触发执行

    class Foo(object):
    
        def __init__(self,a1,a2):
            self.a1 = a1
            self.a2 = a2
    
    obj = Foo(1,2)
    View Code

      2. __call__

        对象后面加括号,触发执行    对象()

    class Foo(object):
    
        def __init__(self,a1,a2):
            self.a1 = a1
            self.a2 = a2
        
        def __call__(self, *args, **kwargs):
            print(11111,args,kwargs)
            return 123
    
    ret = obj(6,4,2,k1=456)
    View Code

      3. __getitem__

          用于索引操作 , 自动触发执行     对象["xx"]

    class Foo(object):
    
        def __init__(self,a1,a2):
            self.a1 = a1
            self.a2 = a2
        
        def __getitem__(self, item):
            print(item)
            return 8
    
    ret = obj['yu']
    print(ret)
    View Code

      4. __setitem__

         用于索引操作 , 自动触发执行     对象["xx"] = 任意

    class Foo(object):
    
        def __init__(self,a1,a2):
            self.a1 = a1
            self.a2 = a2
    
        def __setitem__(self, key, value):
            print(key,value,111111111)
    
    obj['k1'] = 123
    View Code

      5. __delitem__

        析构方法 , 当对象在内存中被释放时 , 自动触发执行   del 对象[xx]

    class Foo(object):
    
        def __init__(self,a1,a2):
            self.a1 = a1
            self.a2 = a2
    
        def __delitem__(self, key):
            print(key)
    
    obj = Foo(1,2)
    del obj['uuu']
    View Code

      6. __add__

        对象 + 对象  自动触发执行    

    class Foo(object):
    
        def __init__(self,a1,a2):
            self.a1 = a1
            self.a2 = a2
    
        def __add__(self, other):
            return self.a1 + other.a2
    
    obj1 = Foo(1,2)
    obj2 = Foo(88,99)
    ret = obj2 + obj1
    print(ret)
    View Code

      7. __enter__ / __exit__

        用于文件操作 , 自动触发执行    with 对象

    class Foo(object):
    
        def __init__(self,a1,a2):
            self.a1 = a1
            self.a2 = a2
    
        def __enter__(self):
            print('1111')
            return 999
    
        def __exit__(self, exc_type, exc_val, exc_tb):
            print('22222')
    
    obj = Foo(1,2)
    with obj as f:
        print(f)
        print('内部代码')
    View Code

      8. __new__

        真正的构造方法

    class Foo(object):
        def __init__(self, a1, a2):     # 初始化方法
            """
            为空对象进行数据初始化
            :param a1:
            :param a2:
            """
            self.a1 = a1
            self.a2 = a2
    
        def __new__(cls, *args, **kwargs): # 构造方法
            """
            创建一个空对象
            :param args:
            :param kwargs:
            :return:
            """
            return object.__new__(cls) # Python内部创建一个当前类的对象(初创时内部是空的.).
    View Code

       9. __str__

    class Foo(object):
        def __init__(self):
            pass
    
        def func(self):
            pass
    
        def __str__(self):
            return "F1"
    
    obj = Foo()
    print(obj,type(obj))
    
    """
    结果:
    F1  类Foo
    """
    View Code

      10. __doc__

    class Foo(object):
        """
        asdfasdfasdfasdf
        """
        def __init__(self):
            pass
    
        def func(self):
            pass
    
        def __str__(self):
            return "F1"
    
    obj = Foo()
    print(obj.__doc__)
    
    """
    结果:
    asdfasdfasdfasdf
    """
    View Code

      11. __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__) 
    print(obj2.__dict__) 
    
    """
    结果:
    {'name': '太白', 'age': 99}
    {'name': '彦涛', 'age': 89}
    """
    View Code

      12. __iter__

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

      经典题型:

    class StarkConfig(object):
        list_display = []
    
        def get_list_display(self):
            self.list_display.insert(0,33)
            return self.list_display
    
    class RoleConfig(StarkConfig):
        list_display = [11,22]
    
    
    s1 = RoleConfig()
    s2 = RoleConfig()
    
    result1 = s1.get_list_display()
    print(result1)
    
    result2 = s2.get_list_display()
    print(result2)
    
    """
    结果:
    [33,11,22]
    [33,33,11,22]
    """
    View Code

      反射                                                                 

    1. issubclass/type/isinstance

      a. issubclass

    class Base(object):
        pass
    
    class Foo(Base):
        pass
    
    class Bar(Foo):
        pass
    
    print(issubclass(Bar,Base)) # 检查第一个参数是否是第二个参数的 子子孙孙类
    View Code

      b. type

        获取当前对象是由哪个类创建

    class Foo(object):
        pass
    
    obj = Foo()
    
    print(obj,type(obj)) 
    
    if type(obj) == Foo:
        print('obj是Foo类型')
    View Code
    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
    
    # result = func(Foo(),Bar(),Foo())
    # print(result)
    
    v1,v2 = func(Foo(),Bar(),Foo())
    print(v1,v2)
    例题

      c. isinstance

        isinstance(xx.xx)检查第一个参数(对象)是否由第二个参数(派生类及基类)的实例.

    class Base(object):
        pass
    
    class Foo(Base):
        pass
    
    obj1 = Foo()
    print(isinstance(obj1,Foo))   # 检查第一个参数(对象)是否是第二个参数(类及父类)的实例。
    print(isinstance(obj1,Base))  # 检查第一个参数(对象)是否是第二个参数(类及父类)的实例。
    
    
    obj2 = Base()
    print(isinstance(obj2,Foo))   # 检查第一个参数(对象)是否是第二个参数(类及父类)的实例。
    print(isinstance(obj2,Base))  # 检查第一个参数(对象)是否是第二个参数(类及父类)的实例。
    View Code

    2. 方法和函数

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

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

      xxx          ----> xxx就是函数

      打印查看:

        function    函数

        method     方法

      代码检查:

    from types import MethodType,FunctionType
    def check(arg):
        """
        检查arg是方法还是函数?
        :param arg:
        :return:
        """
        if isinstance(arg,MethodType):
            print('arg是一个方法')
        elif isinstance(arg,FunctionType):
            print('arg是一个函数')
        else:
            print('不知道是什么')
    View Code

    3. 反射

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

    import xx
    
    v1 = getattr(xx,'x1')   # xx是一个模块
    v2 = getattr(xx,'f1')
    v2('杨森')
    View Code

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

    v3 = hasattr(xx,'x1')
    v4 = hasattr(xx,'f1')
    v4 = hasattr(xx,'f1')
    v5 = hasattr(xx,'xxxxxxx')
    print(v3,v4,v5)
    View Code

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

    setattr(xx,'x2',999)
    v6 = getattr(xx,'x2')
    print(v6)
    View Code
    setattr(xx,'f2',lambda x:x+1)
    v7 = getattr(xx,'f2')
    v8 = v7(1)
    print(v8)
    View Code

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

    delattr(xx,'x1')
    v9 = getattr(xx,'x1')
    print(v9)
    View Code

      总结 : v = getattr(obj,"函数名或方法名") 

        根据字符串为参数(第二个参数) , 去对象(第一个参数)中寻找与之同名的成员.

    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):
                        func_or_val = getattr(handler,val)     # 根据字符串为参数,去模块中寻找与之同名的成员。
                        if isinstance(func_or_val,FunctionType):
                            func_or_val()
                        else:
                            print(func_or_val)
                    else:    
                        print('handler中不存在输入的属性名')        
    应用一
    class Foo(object):
    
        def __init__(self,a1):
            self.a1 = a1
            self.a2 = None
    
    obj = Foo(1)
    
    
    v1 = getattr(obj,'a1')
    print(v1)
    
    setattr(obj,'a2',2)
    
    
    v2 = getattr(obj,'a2')
    print(v2)
    应用二
    class Account(object):
        func_list = ['login', 'logout', 'register']
    
        def login(self):
            """
            登录
            :return:
            """
            print('登录111')
    
        def logout(self):
            """
            注销
            :return:
            """
            print('注销111')
    
        def register(self):
            """
            注册
            :return:
            """
            print('注册111')
    
        def run(self):
            """
            主代码
            :return:
            """
            print("""
                请输入要执行的功能:
                    1. 登录
                    2. 注销
                    3. 注册
            """)
    
            choice = int(input('请输入要执行的序号:'))
            func_name = Account.func_list[choice-1]
    
            # func = getattr(Account,func_name) # Account.login
            # func(self)
    
            func = getattr(self, func_name)  # self.login
            func()
    
    obj1 = Account()
    obj1.run()
    
    obj2 = Account()
    obj2.run()
    View Code

    4. 判断对象是否可以被调用

    def func():
        pass
    
    
    class Foo(object):
        def __call__(self, *args, **kwargs):
            pass
        def func(self):
            pass
    obj = Foo()
    
    
    print(callable(func))
    print(callable(Foo))
    print(callable(obj))
    View Code
  • 相关阅读:
    &&和||解析
    SQL-union union all
    sql杂记
    JAVA杂记
    sql之left join、right join、inner join的区别
    蓝鲸邮箱配置
    快速部署社区版(详解)
    蓝鲸平台安装环境准备
    蓝鲸脚本集合
    zabbix3.4 install
  • 原文地址:https://www.cnblogs.com/xiangweilai/p/9548642.html
Copyright © 2011-2022 走看看