python的魔术方法

什么叫魔术方法:

在python中定义以双下划线开头,有一些python自定义的函数,并且以双下划线为结尾的函数叫做魔法函数

class Company(object):
    def __init__(self, employee_list):
        self.employee = employee_list

    def __getitem__(self, item):
        return self.employee[item]

    def __len__(self):
        return len(self.employee)


company = Company(["tom", "bob", "jane"])

company1 = company[:2]

print(len(company))

for em in company1:
    print(em)

当中间定义了__getitem__方法,就将Company变成了一个可迭代对象,调用for循环时,python会一个一个尝试,直到报错。所以打印print(len(company1))不会报错

__subclasshook__:

这个魔术方法有什么用呢?

使用__subclasshook__后只要具体类定义了与抽象类相同的方法就认为是他的子类

import abc
 
class A(object):
  __metaclass__ = abc.ABCMeta
 
  @abc.abstractmethod
  def say(self):
    return 'say yeah'
 
  @classmethod
  def __subclasshook__(cls, C):
    if cls is A:
      if any("say" in B.__dict__ for B in C.__mro__):
        return True
    return NotTmplementd
 
class B(object):
  def say(self):
    return 'hello'
 
print issubclass(B, A)   # True
print isinstance(B(), A)  # True
print B.__dict__      # {'say': <function say at 0x7f...>, ...}
print A.__subclasshook__(B) # True

 3,__getattr__ 和__getattribute__区别

# __getattr__, __getattribute__
# __getattr__ 就是在查找不到属性的时候调用
from datetime import date


class User:
    def __init__(self, info={}):
        self.in fo = info

    def __getattr__(self, item):
        return self.info[item]

    # def __getattribute__(self, item):
    #     return "bobby"  这个是任何时候都会 进入的,不管是否报错


if __name__ == "__main__":
    user = User(info={"company_name": "imooc", "name": "bobby"})
    print(user.test)
首先调用__getattribute__。如果类定义了__getattr__方法,
那么在__getattribute__抛出 AttributeError 的时候就会调用到__getattr__,

4,property_test

from datetime import date, datetime


class User:
    def __init__(self, name, birthday):
        self.name = name
        self.birthday = birthday
        self._age = 0  # 声明不想被修改的属性

    # def get_age(self):
    #     return datetime.now().year - self.birthday.year

    @property
    def age(self):
        return datetime.now().year - self.birthday.year

    @age.setter
    def age(self, value):
        self._age = value


if __name__ == "__main__":
    user = User("bobby", date(year=1987, month=1, day=1))
    user.age = 30
    print(user._age)
    print(user.age)

其实property主要的作用就是将方法的调用伪装为一个属性的查找方式

5,__new__和__init__区别

class User:
    def __new__(cls, *args, **kwargs):
        print(" in new ")
        return super().__new__(cls)

    def __init__(self, name):
        print(" in init")
        pass


a = int()
# new 是用来控制对象的生成过程, 在对象生成之前
# init是用来完善对象的
# 如果new方法不返回对象, 则不会调用init函数
if __name__ == "__main__":
    user = User(name="bobby")

运行结果如下:

 in new 
 in init

__new__在python3新式类才有的,python2.2之前中是没有的,这个方法允许我们在生成对象之前加逻辑,

所以他传入的参数是cls类。和__init__的根本区别在于,__new__可以自定义类的生成过程的,在__init__之前,不管是传参也好,不传参也好,都需要经过__new__方法

new 是用来控制对象的生成过程, 在对象生成之前

init是用来完善对象的

一般在框架中见得多。(用于元类编程)

原文地址:https://www.cnblogs.com/zhoulixiansen/p/9960245.html