描述符\get/set/delete,init/new/call,元类

6.23 自我总结

1.描述符__get__,__set__,__delete__

描述符是什么:描述符本质就是一个新式类,在这个新式类中,至少实现了____get__(),__set__(),__delete__()中的一个,这也被称为描述符协议

  • __get__():调用一个属性时,触发
  • __set__():为一个属性赋值时,触发
  • __delete__():采用del删除属性时,触发

这三者来对于类的属性生成一个类,然后对一个新类立面的特征进行调用方法

使用方法

class FooSet:

    def __get__(self, instance, owner):
        print('你调用了该方法')

    def __set__(self, instance, value):
        print('你修改了')

    def __delete__(self, instance):
        print('你删除了')

class Foo:
    name = FooSet()

foo = Foo()

#调用生成对象的属性
print(foo.name)

#修改生成对象的属性
foo.name = 123

#删除生成对象的属性
del foo.name
  • 包含这三个方法的新式类称为描述符,由这个类产生的实例进行属性的调用/赋值/删除,并不会触发这三个方法

2.__init__,__new_,__call__

__new__方法的第一个参数是这个类,而其余的参数会在调用成功后全部传递给

__init__方法初始化,这一下子就看出了谁是老子谁是小子的关系。

__call__方法,该方法会在调用对象主要是在定义元类的时候使用时自动触发

class A:
    pass

class B(A):
    def __new__(cls):           #如果没写这一步其实他在init时候默认会进行着一步先
        print("__new__方法被执行")
        return super().__new__(cls)

    def __init__(self):
        print("__init__方法被执行")

b = B()
'''
__new__方法被执行
__init__方法被执行
'''

我们比较两个方法的参数,可以发现__new__方法是传入类(cls),而__init__方法传入类的实例化对象(self),而有意思的是,__new__方法返回的值就是一个实例化对象(ps:如果__new__方法返回None,则__init__方法不会被执行,并且返回值只能调用父类中的__new__方法,而不能调用毫无关系的类的__new__方法)。我们可以这么理解它们之间的关系,__new__是开辟疆域的大将军,而__init__是在这片疆域上辛勤劳作的小老百姓,只有__new__执行完后,开辟好疆域后,__init__才能工作。

绝大多数情况下,我们都不需要自己重写__new__方法,但在当继承一个不可变的类型(例如str类,int类等)时,它的特性就尤显重要了。我们举下面这个例子:

class CapStr(str):
    def __init__(self, string):
        #他在这一步已经传string进去了后面没有意义了
        string = string.upper()
a = CapStr("I love China!")
print(a)
#I love China!

class CapStr(str):
    def __new__(cls, string):
        string = string.upper()
        return super().__new__(cls, string)
a = CapStr("I love China!")
print(a)
#I LOVE CHINA!

3.元类

1.元类的模板

元类定义 class 元类名(type)

class Mymeta(type):
    def __init__(self, class_name, class_bases, class_dic):
        # 加上逻辑,控制类Foo的创建
        super(Mymeta, self).__init__(class_name, class_bases, class_dic)

    def __call__(self, *args, **kwargs):
        # 加上逻辑,控制Foo的调用过程,即Foo对象的产生过程
        obj = self.__new__(self)
        self.__init__(obj, *args, **kwargs)
        # 修改属性为隐藏属性
        obj.__dict__ = {
            '_%s__%s' % (self.__name__, k): v
            for k, v in obj.__dict__.items()
        }

        return obj

2.元类调用

class Foo(object, metaclass=Mymeta):  # Foo = Mymeta(...)
    def __init__(self, name, age, sex):
        self.name = name
        self.age = age
        self.sex = sex

obj = Foo('nick', 18, 'male')

原文地址:https://www.cnblogs.com/pythonywy/p/11074638.html

时间: 2024-07-31 06:35:58

描述符\get/set/delete,init/new/call,元类的相关文章

Servlet注释与部署描述符

值得注意的是,部署描述符优先于注释.换句话说,部署描述符覆盖通过注释机制所规定的配置信息.Web 部署描述符的 3.0 版本在 web-app 元素上包含一种名为 metadata-complete 的新属性.该属性定义了 web 描述符是否完整,或者 web 应用程序的类文件是否针对指定部署信息的注释而进行检查.如果该属性被设置为 true,则部署工具必须忽略类文件中所存在的任何 servlet注释,并只使用描述符中所提及的配置细节.否则,如果没有指定该值或者该值被设置为 false,容器必须

python之属性描述符与属性查找规则

描述符 import numbers class IntgerField: def __get__(self, isinstance, owner): print('获取age') return self.num def __set__(self, instance, value): print('设置age值时') if not isinstance(value, numbers.Integral): raise ValueError('int need') self.num = value

python中名称修饰与描述符

名称修饰 java和C#等其他高级语言中都有private关键字来修饰一个属性或字段是私有的,但是python中并没有private,而是有个与它接近的概念旧式名称修饰.每当在一个属性前面加上__前缀,解释器就会立刻将其重命名: 直接访问会抛异常 利用dir函数查看内部属性 python内部会把__前缀的属性重命名为[_类名+属性名]:因此在python中如果一个属性不是共有的就约定使用双下划线__为前缀,它不会调用任何名称修饰的算法,只是说名这个属性是该类的私有属性. 幸运的是python中还

Python描述符(descriptor)解密

Python中包含了许多内建的语言特性,它们使得代码简洁且易于理解.这些特性包括列表/集合/字典推导式,属性(property).以及装饰器(decorator).对于大部分特性来说,这些"中级"的语言特性有着完善的文档,并且易于学习. 但是这里有个例外,那就是描述符.至少对于我来说,描述符是Python语言核心中困扰我时间最长的一个特性.这里有几点原因如下: 有关描述符的官方文档相当难懂,而且没有包含优秀的示例告诉你为什么需要编写描述符(我得为Raymond Hettinger辩护一

Java描述符的类型

以下内容引用自http://wiki.jikexueyuan.com/project/java/modifier-types.html: 描述符(修饰符)是你添加到那些定义中来改变他们的意思的关键词.Java语言有很多描述符,包括以下这些: 可访问描述符 不可访问描述符 应用描述符,可以在类.方法.变量中加入相应关键字.描述符要先于声明,如下面的例子所示: public class className { // ... } private boolean myFlag; static final

python2.7高级编程 笔记二(Python中的描述符)

Python中包含了许多内建的语言特性,它们使得代码简洁且易于理解.这些特性包括列表/集合/字典推导式,属性(property).以及装饰器(decorator).对于大部分特性来说,这些"中级"的语言特性有着完善的文档,并且易于学习. 但是这里有个例外,那就是描述符.至少对于我来说,描述符是Python语言核心中困扰我时间最长的一个特性.这里有几点原因如下: 有关描述符的官方文档相当难懂,而且没有包含优秀的示例告诉你为什么需要编写描述符(我得为Raymond Hettinger辩护一

[转载]JNI学习积累之二 ---- 数据类型映射、域描述符说明

本文转载于:http://blog.csdn.net/qinjuning 在Java存在两种数据类型: 基本类型 和 引用类型 ,大家都懂的 . 在JNI的世界里也存在类似的数据类型,与Java比较起来,其范围更具严格性,如下: 1.primitive types ----基本数据类型,如:int. float .char等基本类型 2.reference types----引用类型,如:类.实例.数组. 特别需要注意:数组 ------ 不管是对象数组还是基本类型数组,都作为reference

Linux环境编程之文件I/O(一):文件描述符

(一) 首先,对于内核来讲,它是利用"文件描述符"来访问文件的.文件描述符一般是一个非负的整数.当我们用open打开已有的文件或者用creat创建新的文件时,都会返回一个文件描述符.有了文件描述符之后,我们就可以利用该文件描述进行文件的读写,即read.write系统调用都需要文件描述符fd(file descriptor)作为其参数.从以上描述可以看出,当我们想要用read.write等系统调用对文件进行读写等操作之前,必须用open或creat系统调用得到文件的描述符. 一般Uni

Python描述符(descriptor)解密(转)

原文:http://www.geekfan.net/7862/ Python中包含了许多内建的语言特性,它们使得代码简洁且易于理解.这些特性包括列表/集合/字典推导式,属性(property).以及装饰器(decorator).对于大部分特性来说,这些“中级”的语言特性有着完善的文档,并且易于学习. 但是这里有个例外,那就是描述符.至少对于我来说,描述符是Python语言核心中困扰我时间最长的一个特性.这里有几点原因如下: 有关描述符的官方文档相当难懂,而且没有包含优秀的示例告诉你为什么需要编写