python中的一切都是对象

按着我的逻辑走:

  • 首先接受一个公理,「python中的一切都是对象」.不要问为什么,吉大爷(Guido van Rossum,python之父)人当初就是这么设计的,不服去找他评理!
  • 类是python语言的一个元素
  • 那么类也是一个对象

是的,类也是一个对象,因为python中万物皆对象. 只不过类这个对象具有创建对象的能力.

那么问题来了,既然类也是一个对象,那本质上它和其他对象没有啥区别,我们可以对它进行一下操作:

  • 可以赋值给一个变量
  • 可以拷贝
  • 可以增加属性
  • 可以当做入参传递给函数

而且因为类也是一个对象,所以可以在程序运行的时候进行动态的传递.

def choose_class(name):
if name == 'foo':
class Foo:
pass
    <span class="hljs-keyword" style="color: #c678dd; line-height: 26px;">return</span> Foo
<span class="hljs-keyword" style="color: #c678dd; line-height: 26px;">else</span>:
<span class="hljs-class" style="line-height: 26px;"><span class="hljs-keyword" style="color: #c678dd; line-height: 26px;">class</span> <span class="hljs-title" style="color: #e6c07b; line-height: 26px;">Bar</span>:</span>
<span class="hljs-keyword" style="color: #c678dd; line-height: 26px;">pass</span> <span class="hljs-keyword" style="color: #c678dd; line-height: 26px;">return</span> Bar

Myclass = choose_class('foo')

print(Myclass)

print(Myclass())

看一个简单的例子.首先choose_class()函数中动态的创建了类,然后将类作为返回值
然后我们通过一个变量Myclass接收了这个返回值.

看下面两个print,第一个打印的是我们创建出的类. 第二个打印的是我们创建的类创建的对象.

<class '__main__.choose_class.<locals>.Foo'>
<__main__.choose_class.<locals>.Foo object at 0x0000017102113208>

使用type创建类

class type(object)
class type(name, bases, dict)
With one argument, return the type of an object. The return value is a type object and generally the same object as returned by object.__class__.
The isinstance() built-in function is recommended for testing the type of an object, because it takes subclasses into account.

type这个类一看就很特别,因为首字母是小写的...它可以用来创建一个类...

Foo = type('Foo', (object,), {'bar':True})

print(Foo)

foo = Foo()

print(foo)

print(foo.bar)

这里的代码和下面的类创建代码是类似的

class Foo(object):   
bar = True

「向类中添加方法」

Foo = type('Foo', (object,), {'bar': True})

def get_bar(self):

print(self.bar) FooChild = type('FooChild', (Foo,), {'get_bar': get_bar})

print(hasattr(FooChild,'get_bar'))

myfoo = FooChild()

print(myfoo)

myfoo.get_bar()

元类

简单来说,元类就是用来创建类的类. 比如我们上面使用的type就是一个python内置的元类.

比如我们来干一件神器的事情

__metaclass__属性(python3不再支持)

「NOTE!!!」
python3中不再支持__metaclass__属性,而是在定义类的时候使用metaclass=XXXX参数

在写一个类的时候,如果我们指定了__metaclass__属性,就说明我们指明了这个类的元类.

比如我们定义一个类:

class MyClass():
pass

类在定义的时候,它在内存中还没有生成,知道它会被调用,python会做以下的事情:

  1. 在MyClass中寻找__metaclass__属性,如果有,python会在内存中创建一个名字叫MyClass的类对象(注意,是类!对象)
  2. 如果在MyClass中没有找到__metaclass__属性,那么会在它的父类中继续寻找
  3. 如果父类里还没有,那么回到模块底层去找
  4. 如果模块底层还没有,Python会使用type作为元类来创建这个类.

自定义元类

使用函数定义元类

def upper_attr(future_class_name, future_class_parents, future_class_attr):
attrs = ((name, value) for name, value in future_class_attr.items() if not name.startswith('__'))
uppercase_attr = dict((name.upper(), value) for name, value in attrs)
return type(future_class_name, future_class_parents, uppercase_attr) class MyMetacalss(object, metaclass=upper_attr):

bar = 'bip' print(hasattr(MyMetacalss, 'bar'))

print(hasattr(MyMetacalss, 'BAR')) c = MyMetacalss()

print(c.BAR)

使用class来定义元类

先看一下文档中__new__方法的定义.

object.__new__(cls[, ...])
Called to create a new instance of class cls.__new__()is a static method (special-cased so you need not declare it as such) that takes the class of which an instance was requested as its first argument. The remaining arguments are those passed to the object constructor expression (the call to the class). The return value of__new__()should be the new object instance (usually an instance of cls).
Typical implementations create a new instance of the class by invoking the superclass’s __new__() method using super().__new__(cls[, ...]) with appropriate arguments and then modifying the newly-created instance as necessary before returning it.
If __new__()returns an instance of cls, then the new instance’s __init__()method will be invoked like__init__(self[, ...]),where self is the new instance and the remaining arguments are the same as were passed to__new__().
If __new__() does not return an instance of cls, then the new instance’s __init__()method will not be invoked.
__new__() is intended mainly to allow subclasses of immutable types (like int, str, or tuple) to customize instance creation. It is also commonly overridden in custom metaclasses in order to customize class creation.

明白了__new__方法,那改写起来就简单了

class Upper(type):
def __new__(cls, name, bases, attrs):
attr = ((name, value) for name, value in attrs.items() if not name.startswith('__'))
uppercase_attr = dict((name.upper(), value) for name, value in attr)
return type.__new__(cls, name, bases, uppercase_attr)

还有一种写法是通过调用父类的__new__()方法来返回类对象. 如果子类需要重写__new__()方法的话,一般要调用父类的__new__()方法.

class Upper(type):
def __new__(cls, name, bases, attrs):
attr = ((name, value) for name, value in attrs.items() if not name.startswith('__'))
uppercase_attr = dict((name.upper(), value) for name, value in attr)
return super(Upper,cls).__new__(cls, name, bases , uppercase_attr)

另外通过上面的文档,我们也能知道一个对象创建的时候会有那些操作.

  1. 调用__new__()方法来创建内存空间
  2. 之后调用__init__()方法来初始化参数.

参考资料:

  1. python中的元类-简书
  2. 深刻理解Python中的元类(metaclass)以及元类实现单例模式

python随用随学-元类的更多相关文章

  1. 【python进阶】详解元类及其应用2

    前言 在上一篇文章[python进阶]详解元类及其应用1中,我们提到了关于元类的一些前置知识,介绍了类对象,动态创建类,使用type创建类,这一节我们将继续接着上文来讲~~~ 5.使⽤type创建带有 ...

  2. Python高级语法-贯彻回顾-元类(4.99.1)

    @ 目录 1.为什么要掌握元类 2.正文 关于作者 1.为什么要掌握元类 在django中编写models的时候遇到了元类的相关操作 并且在mini-web框架编写的时候也遇到了相关的问题 意识到深入 ...

  3. Python学习_13_继承和元类

    继承 继承的含义就是子类继承父类的命名空间,子类中可以调用父类的属性和方法,由于命名空间的查找方式,当子类中定义和父类同名属性或者方法时,子类的实例调用的是子类中的属性,而不是父类,这就形成了pyth ...

  4. 通过 python的 __call__ 函数与元类 实现单例模式

    简单一句话,当一个类实现__call__方法时,这个类的实例就会变成可调用对象. 直接上测试代码 class ClassA: def __call__(self, *args, **kwargs): ...

  5. 【python进阶】详解元类及其应用1

    前言 元类在python中是很重要的一部分,我将分两次去讲解元类及其应用,此篇为详解元类及其应用第一篇,下面开始今天的说明~~~ 1. 类也是对象 在⼤多数编程语⾔中,类就是⼀组⽤来描述如何⽣成⼀个对 ...

  6. python中的单例模式、元类

    单例模式 单例模式(Singleton Pattern)是一种常用的软件设计模式,该模式的主要目的是确保某一个类只有一个实例存在.当你希望在整个系统中,某个类只能出现一个实例时,单例对象就能派上用场. ...

  7. python面试题~反射,元类,单例

    1 什么是反射?以及应用场景? test.py def f1(): print('f1') def f2(): print('f2') def f3(): print('f3') def f4(): ...

  8. python之禅---对象与元类

    众所周知,python是一门面向对象的编程语言,python中一切皆对象,那么我们先探讨一下什么是对象. 一.对象 在生活中一个事物就是一个对象,比如:一只猫就是一个对象,猫的体型.猫毛的颜色等是它的 ...

  9. 【原创】Python 对象创建过程中元类, __new__, __call__, __init__ 的处理

    原始type: type是最原始的元类,其__call__方法是在你使用" t_class = type(classname_string, base_classes_tuple, attr ...

随机推荐

  1. Python 语言基础

    Python 语言基础 Python 开发环境 计算机组成 编程语言(计算机语言)是人们为了控制计算机,而设计的一种符号和文字的组合,从而实现向计算机发出指令. 形式是符号和文字的组合 目的是为了控制 ...

  2. 微信中的APP、公众号、小程序的openid及unionid介绍

    微信中的APP.公众号.小程序的openid及unionid介绍 1.unionid 如果开发者拥有多个移动应用.网站应用.和公众帐号(包括小程序),可通过 UnionID 来区分用户的唯一性,因为只 ...

  3. 苹果为啥不愿意替美国FBI解锁,这是一种创新态度?

    国外媒体报道,苹果计划对iPhone进行安全更新,最新版的iOS会在手机锁定一个小时后禁用手机充电和数据端口,这意味着,消费者丢失手机或者非正常离开iPhone之后,可以通过锁定手机,来避免手机数据被 ...

  4. Java面试题1-附答案

    List和Set比较,各自的子类比较 对比一:Arraylist与LinkedList的比较 1.ArrayList是实现了基于动态数组的数据结构,因为地址连续,一旦数据存储好了,查询操作效率会比较高 ...

  5. Django获取当前时间和Linux系统时间不一致

    配置文件中修改:TIME_ZONE的值改为上海,USE_TZ的值改为False,重启项目即可

  6. Spring @Column的注解详解

    就像@Table注解用来标识实体类与数据表的对应关系类似,@Column注解来标识实体类中属性与数据表中字段的对应关系. 该注解的定义如下: @Target({METHOD, FIELD}) @Ret ...

  7. RELAX NG

    RELAX NG (读作"relaxing"), 是一种基于语法的XML模式语言,可用于描述.定义和限制XML词汇表. 最初的XML模式语言是DTD,但是因为DTD语法丑陋, 表达 ...

  8. [从 0 开始的 Angular 生活]No.38 实现一个 Angular Router 切换组件页面(一)

    前言 今天是进入公司的第三天,为了能尽快投入项目与成为团队可用的战力,我正在努力啃官方文档学习 Angular 的知识,所以这一篇文章主要是记录我如何阅读官方文档后,实现这个非常基本的.带导航的网页应 ...

  9. Leetcode13_罗马数字转整数

    题目 罗马数字包含以下七种字符: I, V, X, L,C,D 和 M. 字符 数值I 1V 5X 10L 50C 100D 500M 1000例如, 罗马数字 2 写做 II ,即为两个并列的 1. ...

  10. Leetcode1_两数之和

    题目 给定一个整数数组 nums 和一个目标值 target,请你在该数组中找出和为目标值的那 两个 整数,并返回他们的数组下标. 你可以假设每种输入只会对应一个答案.但是,你不能重复利用这个数组中同 ...