zoukankan      html  css  js  c++  java
  • 类的成员-反射-双下方法

     类的私有成员:

    私有成员只是做了一个简单是变相加密,直接访问不了

    1.私有静态属性

    在变量名前加 __             可以在本类的内部访问,在类的外部和派生类中无法访问

    class A:
        country = '中国'
        __country = '加拿大' # 私有静态属性
    
        def func(self):
            print(A.country)
            print(A.__country)
    
    class B(A):
    
        def func1(self):
            print(super().country)
    
    obj = A()
    
    # 在类的内部访问: 可以
    obj.func()
    
    # 类的外部访问: 不可以
    print(A.__country)
    obj.__country
    
    # 在派生类访问: 不可以
    obj1 = B()
    obj1.func1()

    2.私有方法

    可以在本类的内部访问,在类的外部和派生类中无法访问

    class A:
        def __f1(self):
            print('in A f1')
    
        def func(self):
            self.__f1()
    
    class B(A):
        def f1(self):
            super().__f1()
    
    obj = A()
    
    # 类内部可以访问
    obj.func()
    
    # 类外部不可以访问
    obj.__f1()
    
    # 类的派生类: 不可以访问
    b = B()
    b.f1()

    3.私有对象属性

    class A:
    
        def __init__(self,name,age):
            self.name = name
            self.__age = age
    
        def func(self):
            print(self.__age)
    
    obj = A('静哥',24)
    
    #类内部可以访问:
    obj.func()
    #类的外部不能访问:
    print(obj.__age)
    #派生类也不能访问

    什么时候使用私有成员:

    密码,年龄,个人信息,只是类内部使用的方法等,需要设置私有成员

    类的其他成员

    1)类方法:

    @classmethod 

    通过类名调用的方法,第一个参数主动接收类名,为了区分,参数名为cls

    对象也可以调用类方法,传给cls的参数也是类空间(一般不这么用)

    主动接收类名,与类的静态属性相关的需求,与对象无关的功能需要类方法

    class Student:
        stu_num = 0
        def __init__(self,name,age):
            self.name = name
            self.__age = age
            Student.calc_num()    # 应该放在__new__里面
    
        @classmethod
        def calc_num(cls):
            cls.stu_num += 1
    
        @classmethod
        def get_num(cls):
            return cls.stu_num
    
    denge = Student('邓哥',18)
    jinge = Student('静哥',18)
    print(Student.get_num())
    
    结果:
    2

    2)静态方法

    @staticmethod

    不依赖与类以及对象的方法,是函数

    静态方法虽然不依赖与对象,类,但是为了保持代码的整体性和一致性,才将其设置为静态方法,而不是放在类外面当普通函数用

    class A:
        def __init__(self,name,age):   # 双下方法 特殊方法
            self.name = name
            self.__age = age
    
        def func(self):              # 实例方法:通常是通过对象去调用的方法,主动将对象传给self
            print('in func')
    
        @classmethod
        def func1(cls):             # 类方法: 是通过类名调用的方法,第一个参数主动接受类名
            print('类方法')
    
        @staticmethod             # 静态方法:不依赖于类以及对象的方法,是函数.
        def func2():
            pass

    3)属性

    @property

    将方法伪装成属性,虽然在代码逻辑上没有提升,但是看起来更合理

    class Bmi:
        def __init__(self,name,weight,height):
            self.name = name
            self.__weight = weight
            self.height = height
        @property
        def bmi(self):
            return self.__weight/(self.height**2)
    
    obj = Bmi('hu',75,1.75)
    print(obj.bmi)      #bmi本身是一个方法,通过@property装饰器之后,直接用调用属性的方式进行打印就可以

    另外有更改和删除的方法:

    class A:
        @property
        def AAA(self):
            print('调用属性')
    
        @AAA.setter
        def AAA(self,new):           #更改属性时要传参
            print('更改属性')
    
        @AAA.deleter
        def AAA(self):
            print('删除属性')
    
    obj = A()
    # obj.AAA               #调用
    # obj.AAA = 111      #更改
    # del obj.AAA           #删除
    ####练习:
    class Goods:
        def __init__(self,name,money,sale):
            self.name = name
            self.money = money
            self.sale = sale
    
        @property
        def price(self):
            return self.money*self.sale
        @price.setter
        def price(self,new):
            self.money = new / self.sale
    
    apple = Goods('苹果',5,0.9)
    #计算现价
    # print(apple.price)
    #要求改过之后的价格为10
    apple.price = 10
    print(apple.price)

    源码见的最多的是 property

    对象自己的属性 如果与类的伪装的属性重名时,对对象属性进行修改时,则只会执行@setter方法

    为了避免这个坑,给对象设置的属性名,不要与property伪装的属性名重名

    4)isinstance issubclass

    isinstance(o,a)         判断o是否是a或者a的派生类的对象

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

     issubclass(a,b)   判断a是否是b的子类或孙类

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

    list str等这些可迭代对象与 Iterable是什么关系?

    from collections import Iterable
    l1 = [1,2,3]
    print(isinstance(l1,Iterable))     # l1是Iterable(派生类)的实例的对象

    list类与Iterable类是什么关系?

    print(issubclass(list,Iterable))       # list是Iterable的派生类

    元类

    python 一切皆对象原则

    类也是对象

    type 元类,也叫构建类,产出了python中大量的内置类(str,list...)以及自建类

    反射

    通过字符串对对象进行相应的操作(对象:实例化对象 类 其他模块 本模块)

    hasattr() 判断有没有

    getattr() 取值

    setattr() 设置(增)

    delattr() 删除

    class A:
        country = '中国'
        def __init__(self,name,age):
            self.name = name
            self.age = age
        def func(self):
            print('in A func')
    
    obj = A('棍哥',20)
    print(hasattr(obj,'name'))   #判断有没有'name'属性
    print(getattr(obj,'name'))   #取'name'的值
    setattr(obj,'height',180)    #增加'height'
    print(obj.__dict__)
    delattr(obj,'age')           #删除'age'
    print(obj.__dict__)

    注意事项:

    反射只能用在都可以通过 . 去操作的对象

    class User:
        def login(self):
            print('欢迎来到登录页面')
    
        def register(self):
            print('欢迎来到注册页面')
    
        def save(self):
            print('欢迎来到存储页面')
    
    while 1:
        choose = input('请输入').strip()
        obj = User()
        if hasattr(obj,choose):
            getattr(obj,choose)()

    判断函数与方法:

    def func():
        pass
    
    class A:
        def func1(self):
            pass
    #1.通过打印名字的方式判断
    print(func)         #函数
    print(A.func1)     #函数
    obj = A()
    print(obj.func1)   #方法
    #2.通过引用模块
    from types import FunctionType   函数 
    from types import Methodtype     方法
    print(isinstance(func,FunctionType))         # True
    print(isinstance(A.func1,FunctionType))      # True
    print(isinstance(obj.func1,FunctionType))    # Flase
    print(isinstance(obj.func1,MethodType))      # True

    之前学的函数就是函数

    通过类名调用,就是函数

    通过实例调用,就是方法

    类中的静态方法是函数

    类中的类方法,是方法

    函数与方法的区别:

    函数是显性传参,不依赖于对象

    方法是隐形传参(默认接收对象空间或者类空间),依赖对象,类

    特殊的双下方法

    解释器提供的,由__方法名__的具有特殊意义的方法,主要是python源码程序员使用的元编程,开发中尽量不使用

    __init__ 类名()触发

    1)len ****

    一个实例能否使用len操作,完全取决于它的类中有没有__len__方法

    class A:
        def __init__(self,name,age,sex,weight):
            self.name = name
            self.age = age
            self.sex = sex
            self.weight = weight
        def __len__(self):
            print(666)
            return len(self.__dict__)
    obj = A('刘姐',18, '',100)
    len(obj)            # 只要对对象len() 就会触发对象从属于的类中的 __len__  
    print(len(obj))

    结果:
    666
    666
    4

    2)__hash__

    class A:
        def __init__(self):
            pass
        def __hash__(self):
            return 666
    obj = A()
    print(hash(obj))       #触发__hash__方法

    3)__str__

    class A:
        def __init__(self,name,age):
            self.name = name
            self.age = age
    
        def __str__(self):
            return str(self.__dict__)
    
    obj = A('alex',73)
    print(obj)
    
    结果:
    {'name': 'alex', 'age': 73}

    4)__repr__

    class A:
        def __repr__(self):
            return 'alex'
    obj = A()
    print(repr(obj))    
    
    结果:
    alex


    5)_call__:    对象() 执行 __call__方法     *****

    class A:
    
        def __init__(self):
            print(111)
    
        def __call__(self, *args, **kwargs):
            print(666)
    
    obj = A()    #触发__init__方法
    obj()        #触发__call__方法

    6)__eq__

    class A:
        def __init__(self):
            self.a = 1
            self.b = 2
    
        def __eq__(self,obj):
            print(666)
    
    a = A()
    b = A()
    print(a == b)  # 同一个类的两个实例进行比较就会触发类中 __eq__方法
    
    结果:
    666
    None

    6)__del__ 析构方法

    class A:
        def __del__(self):
            print(666)
    obj = A()
    
    结果:
    666

    7)__new__  构造方法 ***

    类名() 调用__new__方法

    class A:
        def __init__(self,name,age):
            self.name = name
            self.age = age
            print(111)
    
        def __new__(cls, *args, **kwargs):
            print(222)
            return object.__new__(cls)
    
    obj = A('barry',18)
    
    结果:
    222
    111

    单例模式 规定一个类只能实例化一个对象(面试题)

    class A:
        pass
    ret = A()
    print(ret)
    ret = A()
    print(ret)
    ret = A()
    print(ret)
    #以上三个ret内存地址是不同的
    class A:
        __instance = None
        def __new__(cls, *args, **kwargs):
            if not cls.__instance:
                obj = object.__new__(cls)
                cls.__instance = obj
            return cls.__instance
    
    ret = A()
    print(ret)
    ret = A()
    print(ret)
    ret = A()
    print(ret)
    #以上三个ret内存地址是一样的

    8)__item__:    *****

    对对象进行类似于字典的操作的时候,就会触发相应的方法.

    class Foo:
        def __init__(self,name):
            self.name=name
    
        def __getitem__(self, item):
            return self.__dict__[item]
    
        def __setitem__(self, key, value):
            # print(key,value)
            self.__dict__[key]=value
        def __delitem__(self, key):
            print(key)
            print('del obj[key]时,我执行')
            self.__dict__.pop(key)
    
        def __delattr__(self, item):
            print('del obj.key时,我执行')
            self.__dict__.pop(item)
    
    f = Foo('alexsb')
    print(f['name'])
    print(f.__dict__)
    f['name'] = 'sb'  # 触发 __setitem__方法
    print(f.__dict__)
    del f['name']
    
    结果:
    alexsb
    {'name': 'alexsb'}
    {'name': 'sb'}
    name
    del obj[key]时,我执行


    9)上下文管理

    class A:
    
        def __init__(self, text):
            self.text = text
        def __enter__(self):    # 开启上下文管理器对象时触发此方法
            self.text = self.text + '您来啦'
            return self        # 将实例化的对象返回f1
        def __exit__(self, exc_type, exc_val, exc_tb):  # 执行完上下文管理器对象f1时触发此方法
            self.text = self.text + '这就走啦'
    
    f1 = A('大爷')
    # print(f1.text)
    with A('大爷') as f1:
        print(f1.text)
    print(f1.text)   
    
    
    结果:
    大爷您来啦
    大爷您来啦这就走啦
  • 相关阅读:
    python面试题目【转1】
    让python和C/C++联姻【转】
    python面试模拟真题讲解
    JavaScript真的要一统江湖了
    WebApp
    Linux服务器之SSH
    web服务之http
    SNMP简单网络管理协议
    Storm,Spark和Samza
    Stream computing
  • 原文地址:https://www.cnblogs.com/sandy-123/p/10370283.html
Copyright © 2011-2022 走看看