九.python面向对象(双下方法内置方法)

一. 内置方法

1.__call__

class Da(object):
     def __init__(self,a1,a2):
         self.a1=a1
         self.a2=a2
     def cc(self):
         print("我是啊哈哈哈")
def __call__(self, *args, **kwargs): print(self.a1) print(self.a2) print(args) print(kwargs) print("对象自动执行!!!!!!!!!!!!!!!!!!!1") obj=Da(11,22) print(obj.a1) print(obj.a2) print("**********************************************8") # 这是使用__call__ 方法 对象传参数自动执行 obj(1,2,3,name="张三",age=555)


# 11
# 22
# **********************************************8
# 11
# 22
# (1, 2, 3)
# {'name': '张三', 'age': 555}
# 对象自动执行!!!!!!!!!!!!!!!!!!!1

2. __getitme__

class Da(object):
def __init__(self, a1, a2):
self.a1 = a1
self.a2 = a2

@property
def cc(self):
print("我是啊哈哈哈")

def __getitem__(self, item):
# print(item)
print(self.a1)
self.cc
return item

# return self.__dict__[itme]


obj = Da(11, 22)
aa = obj["k1"]
print(aa) # k1

print("*********************************")
bb = obj["name", "哈哈哈", "66666"]
print(bb) # ('name', '哈哈哈', '66666')

# 11
# 我是啊哈哈哈
# k1
# *********************************
# 11
# 我是啊哈哈哈
# ('name', '哈哈哈', '66666')

 3.__setitem__

# __setitem__
class Da(object):
    def __init__(self, a1, a2):
        self.a1 = a1
        self.a2 = a2
    def cc(self):
        print("我是啊哈哈哈")

    def __setitem__(self, key, value):
       print(key,value)
       print(self.a1)
       self.cc()
       # self.__dict__[key]=value

obj = Da(11, 22)
obj.cc()
print("***********************")
aa=obj["k1"]=588888

# 我是啊哈哈哈
# ***********************
# k1 588888
# 11
# 我是啊哈哈哈

4.__delitme__

# __delitme__
class Da(object):
    def __init__(self, a1, a2):
        self.a1 = a1
        self.a2 = a2

    def cc(self):
        print("我是啊哈哈哈")

    def __delitem__(self, key):
        print(key)
        # del self.__dict__[key]
obj = Da(11, 22)
obj.cc()
print("*****************************************")
del obj["lover"]
print(obj.__dict__)

# 我是啊哈哈哈
# *****************************************
# lover
# {'a1': 11, 'a2': 22}
5.__iter__
# __iter__
class Da(object):
    def __init__(self, a1, a2):

        self.a1 = a1
        self.a2 = a2
    def cc(self):
        print("我是啊哈哈哈")


    def  __iter__(self):
         # return  iter([11,22,333])
        yield 1
        yield 22
a=Da(1,2)
for i in a:
    print(i)

# 如果 要把不可迭代对象 -》可迭代对象
# 在类中定义 __iter__方法
# iter 内部返回一个迭代器  生成器也是迭代器的一种  所以生成器也可以

# 1
# 22
6 . __getattr__
class Da(object):
    num=666
    def __init__(self,name):
        self.name=name

    def aa(self):
        print(f'我的名字叫---{self.name}')


    def __getattr__(self, item):
            # print("我是")
            print(item)

cc=Da("张无忌")
cc.age    #调用了一个不存的属性 才会触发 __getattr___
cc.bb
# age
# bb


class Test(object):
def __init__(self, name):
self.name = name

def __getattr__(self, value):
if value == 'address':
return 'China'
test = Test('美国')
print(test.name)
print(test.address)
test.address = '北京'
print(test.address)
# 美国
# China
# 北京



# __getattribute__  查找属性无论是否存在,都会执行

class Da(object):
def __init__(self,age):
self.age=age
def __getattribute__(self, item):

print(item,"嗡嗡嗡嗡嗡嗡嗡嗡嗡嗡嗡嗡嗡嗡嗡")
print("********************")
# print(self.age)

aa=Da(55)
aa.bbbbbbbb
print(aa.age)


class Test(object):
def __init__(self, name):
self.name = name

def __getattribute__(self, value):
if value == 'address':
return 'China'

test = Test('上海')
print(test.name)
print(test.address)
test.address = '北京'
print(test.address)
# None
# China
# China
 7. __setattr__
class Da(object):
    num=666
    def __init__(self,name):
        self.name=name
        
    def aa(self):
        print(f'我的名字叫---{self.name}')

    def __setattr__(self, key, value):
        self.__dict__[key] = value
        print(key,value)


cc=Da("张无忌")                #  __setattr__   设置属性时会促发 __setattr__
cc.age=18
cc.hod="篮球"
print(cc.__dict__)

# name 张无忌
# age 18
# hod 篮球
# {'name': '张无忌', 'age': 18, 'hod': '篮球'}
8.__delattr__
# __delattr__  删除一个会促发这个方法
class Fa(object):
    def __init__(self, name):
        self.name = name
    def __setattr__(self, key, value):
        if type(value) is str:
            print("执行__setattr__方法", key, value)
            self.__dict__[key] = value
        else:
            print("必须是字符串")

    def __delattr__(self, item):
        print("执行 __delattr__ 方法", item)


a4 = Fa("张三")
a4.age = "25岁"
a4.sex = ""
a4.shenggao = 188  # type 是数字就添加不进去
print(a4.__dict__)
del a4.name                        # __delattr__  删除一个会促发这个方法

"""执行__setattr__方法 name 张三
执行__setattr__方法 age 25岁
执行__setattr__方法 sex 男
必须是字符串
{'name': '张三', 'age': '25岁', 'sex': '男'}
执行 __delattr__ 方法 name
"""
9. __new__    __init__
class Da(object):
    def __init__(self, a1, a2):
        self.a1 = a1
        self.a2 = a2

    def cc(self):
        print("我是啊哈哈哈")

    def __new__(cls, *args, **kwargs):
        print(1)

obj = Da(11, 22)
# print(obj.a1)     执行不到
# 1

print("************************************************************************************88")

# 注意 在类中 使用__init__初始化函数前    是自动默认会执行__new__构造方法
# 虽然我们不用添加__new__  但是我们要知道  在使用 __init__初始化 前 python 内部就自动调用了 __new__构造方法
class Da(object):
    def __init__(self, a1, a2):
        print("这里是初始化")
        self.a1 = a1
        self.a2 = a2
    def cc(self):
        print("我是啊哈哈哈")

    def __new__(cls, *args, **kwargs):
        print("这里是构造方法")
        print(cls)
        return object.__new__(cls)  #  构造方法必须返回   object.__new__(cls)  才能执行__init__初始化对象

obj = Da(11, 22)
print(obj.a1)

# 这里是构造方法
# <class '__main__.Da'>
# 这里是初始化
# 11




# __new__ 的作用
# # 1、__new__方法主要是当你继承一些不可变的class时(比如int, str, tuple), 提供给你一个自定义这些类的实例化过程的途径。
# # 假如我们需要一个永远都是正数的整数类型,通过集成int,我们可能会写出这样的代码。
#
#
# # 3、__new__必须要有返回值,返回实例化出来的实例,这点在自己实现__new__时要特别注意,可以return父类(通过super(当前类名, cls))
# # __new__出来的实例,或者直接是object的__new__出来的实例
#
# # 4、__init__有一个参数self,就是这个__new__返回的实例,__init__在__new__的基础上可以完成一些其它初始化的动作,__init__不需要返回值

 10 . __add__
# __add__
# 对象可以相加   加减  乘  除
class Da(object):
    def __init__(self, a1, a2):
        self.a1 = a1
        self.a2 = a2
    def cc(self):
        print("我是啊哈哈哈")

    def __add__(self, other):
        return self.a1+other.a1
a=Da(1,2)
b=Da(100,20)
print(a+b)
# 101
11. __del__
# 析构函数(destructor) 与构造函数相反,当对象结束其生命周期时(例如对象所在的函数已调用完毕),系统自动执行析构函数。析构函数往往用来做"清理善后" 的工作
# (例如在建立对象时用new开辟了一片内存空间,delete会自动调用析构函数后释放内存)。
# 析构函数 :__del__()释放对象自动调用

class person(object):
    def run(self):
        print("run")
    def __init__(self, name, age, height, weight):
        self.name = name
        self.age = age
        self.height = height
        self.weight = weight
    def __del__(self):
       print("这里是析构函数")
per
= person("张三", 25, 300, 100) # 释放对象 就相当于删除了 就不能访问了 这是手动释放 del per # 在函数里定义的对象会在函数结束时自动释放(删除) 可以减少内存浪费空间 def fun(): per2 = person("李四", 1000, 2000, 30000) print(per2.name) fun()

#这里是析构函数
# 李四
# 这里是析构函数



# __del__也称之为析构方法
#
# __del__会在对象被删除之前自动触发

class People:
def __init__(self, name, age):
self.name = name
self.age = age
self.f = open('test.txt', 'w', encoding='utf-8')

def __del__(self):
print('run======>')
# 做回收系统资源相关的事情
self.f.close()

obj = People('egon', 18)
del obj # del obj会间接删除f的内存占用,但是还需要自定制__del__删除文件的系统占用
print('主')


# run======>
# 主
 
 13. __len__
# __len__  和 len配合使用
class Students(object):
    def __init__(self, *args):
        self.names = args
    def __len__(self):
        return len(self.names)

aa=Students("111",222)

print(aa)
print(len(aa))

# 2
14. __str__
 # __str__()函数的作用:
# 不知道大家再写程序是,打印一个实例化对象时,打印的其实时一个对象的地址。而通过__str__()函数就可以帮助我们打印对象中具体的属性值,或者你想得到的东西。
#
# 因为再python中调用print()打印实例化对象时会调用__str__()如果__str__()中有返回
class ss:
    def __init__(self,age,name):
        self.age = age
        self.name = name
    def __str__(self):
        return str(self.age)+",,wozenmezhemeshuai,,"+self.name

s = ss(21,'aitebao')
print(s)

# 21,,wozenmezhemeshuai,,aitebao
 15. __hash__
# __hash__  hash() 用于获取取一个对象(字符串或者数值等)的哈希值。
class F(object):
      def __init__(self,name,sex):
          self.name=name
          self.sex=sex
      def __hash__(self):
          return  hash(self.name+ self.sex)

a=F("张三","")
b=F("张三","1111")
print(hash(a))
print(hash(b))
16.__eq__
# 如果不实现__eq__方法,那么自定义类型会调用默认的__eq__方法, 通过默认方法进行比较的相等条件相当严格,只有自己和自己比才会返回True,表现如下
# __eq__
# class B(object):
#     def __int__(self,name):
#         self.name=name
#     def __eq__(self,other):
#         if self.name==other.name:
#             return  True

# c1=B("张三")
# c2=B("李四")

class Item:
  def __init__(self, name):
      self. name=  name
  def __eq__(self, other):
     if self. name== other. name:
         return True
     else:
         return  False
first = Item('hello')
second = Item('hello')
print(first == second) # True
17.__slots__ 
__slots__是一个类变量,变量值可以是列表,元祖,或者可迭代对象,也可以是一个字符串(意味着所有实例只有一个数据属性)

使用点来访问属性本质就是在访问类或者对象的__dict__属性字典(类的字典是共享的,而每个实例的是独立的)

  • 字典会占用大量内存,如果你有一个属性很少的类,但是有很多实例,为了节省内存可以使用__slots__取代实例的__dict__

  • 当你定义__slots__后,__slots__就会为实例使用一种更加紧凑的内部表示。实例通过一个很小的固定大小的数组来构建,而不是为每个实例定义一个字典,这跟元组或列表很类似。在__slots__中列出的属性名在内部被映射到这个数组的指定小标上。使用__slots__一个不好的地方就是我们不能再给实例添加新的属性了,只能使用在__slots__中定义的那些属性名。



class
Foo: __slots__='x' f1=Foo() f1.x=1 f1.y=2#报错 print(f1.__slots__) #f1不再有__dict__ class Bar: __slots__=['x','y'] n=Bar() n.x,n.y=1,2 n.z=3#报错
# __slots__  省内存
class Person(object):
     # 意思__slots__ 里面定义的属性 在实例化对象赋值时 只能使用里面定义好了的字段 不然会报错   这样会省内存
    __slots__ = ("name", "age", "speak")
per = Person()
per.name="哈哈哈哈"
per.age=666
per.speak=4444444
# 意思就是只能添加__slots__里面定义的属性
#per.aa=6666   #会报错因为__slotl__里面没有定义
# 使用__slots__时 __dict__ 也不能用
print(per.__slots__)
print(Person.__slots__)


print("*************************************************************************8")

class Foo:
    __slots__=['name','age']
f1=Foo()
f1.name='alex'
f1.age=18
print(f1.__slots__)
# ['name', 'age']
f2=Foo()
f2.name='egon'
f2.age=19
print(f2.__slots__)
# ['name', 'age']
# f1与f2都没有属性字典__dict__了,统一归__slots__管,节省内存
print(Foo.__dict__)
# {'__module__': '__main__', '__slots__': ['name', 'age'], 'age': <member 'age' of 'Foo' objects>, 'name': <member 'name' of 'Foo' objects>, '__doc__': None}
from types import MethodType

# 创建一空类
class Person(object):
    # 想添加什么属性就写在里面
    __slots__ = ("name", "age", "speak")
per = Person()

per.name = "张师傅"
print(per.name)

# 动态的添加方法     必须引入一个模块
def say(self):
    print("动态的添加方法" + self.name)
    print("啊哈哈哈哈哈哈哈")
per.speak = MethodType(say, per)
per.speak()

"""
思考: 如果我们想要 限制实例的属性怎么办
比如 只允许给对象添加name age height 特定的属性
解解方法:
      定义类的时候 定义一个特殊的属性 (__slots__)可以限制动态属性的添加
      """
per.age = 222222
print(per.age)

# 张师傅
# 动态的添加方法张师傅
# 啊哈哈哈哈哈哈哈
# 222222
from types import MethodType

# 创建一空类
class Person(object):
    pass
per = Person()

per.name = "张师傅"
print(per.name)

# 动态的添加方法     必须引入一个模块
def say(self):
    print("动态的添加方法" + self.name)
per.speak = MethodType(say, per)
per.speak()

# 张师傅
# 动态的添加方法张师傅

print(per.__dict__)

# 张师傅
# 动态的添加方法张师傅
# {'name': '张师傅', 'speak': <bound method say of <__main__.Person object at 0x0000025D818888D0>>}
18 __doc__返回类的注释信息
class Foo:
    '我是描述信息'
    pass
print(Foo.__doc__)
# 我是描述信息

print("**********************************************")

# 该属性无法继承给子类
class Foo:
    '我是描述信息'
    pass
class Bar(Foo):
    pass
print(Bar.__doc__) #该属性无法继承给子类

# None

 19 .__class__       __module__

 



 
 
 
原文地址:https://www.cnblogs.com/Sup-to/p/10887811.html