首页 > 其他 > 详细

类的成员-反射-双下方法

时间:2019-02-13 17:16:02      阅读:152      评论:0      收藏:0      [点我收藏+]

 类的私有成员:

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

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)   


结果:
大爷您来啦
大爷您来啦这就走啦

 

类的成员-反射-双下方法

原文:https://www.cnblogs.com/sandy-123/p/10370283.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!