一、类也是对象

当我们定义一个变量或者函数的时候,我们可以在globals()的返回值字典中找到响应的映射:

def A():
print("This is function A") myname = "Leo" print(globals())

我们可以得到以下结果:

{
'__name__': '__main__',
'__doc__': None,
'__package__': None,
'__loader__': <_frozen_importlib_external.SourceFileLoader object at 0x0000021F09971CC0>,
'__spec__': None,
'__annotations__': {},
'__builtins__': <module 'builtins' (built-in)>,
'__file__': 'D:/pycharm_project/leo1201/basic_class/test.py',
'__cached__': None,
'A': <function A at 0x0000021F099AC1E0>,
'myname': 'Leo'
}

我们可以发现我们定义的函数A和变量myname都在这个字典中,这个字典中记录的映射,实际上就是全局变量(也就是可以直接调用的对象)。

那么我们定义的类是什么呢:

class B(object):
pass print(globals())

得到的结果:

{
'__name__': '__main__',
'__doc__': None,
'__package__': None,
'__loader__': <_frozen_importlib_external.SourceFileLoader object at 0x0000021F09971CC0>,
'__spec__': None,
'__annotations__': {},
'__builtins__': <module 'builtins' (built-in)>,
'__file__': 'D:/pycharm_project/leo1201/basic_class/test.py',
'__cached__': None,
'B': <class '__main__.B'>
}

我们可以看到,类B也在该字典中。所以,我们说类实际上也是一个全局对象,只是这个对象的功能可以生成其他的对象而已。

二、内建属性

在上面所看到的globals()返回的字典中,我们并未看到我们常用的print()等直接调用的函数,这是因为这些内建函数都在'__builtin__'中:

global_dict = globals()
print(global_dict['__builtins__']) # 打印 <module 'builtins' (built-in)>

我们打印一下__builtin__字典:

global_dict = globals()
print(global_dict['__builtins__'].__dict__)

得到一个很长的字典:

{
'__name__': 'builtins',
'__doc__': "Built-in functions, exceptions, and other objects.\n\nNoteworthy: None is the `nil' object; Ellipsis represents `...' in slices.",
'__package__': '',
'__loader__': <class '_frozen_importlib.BuiltinImporter'>,
'__spec__': ModuleSpec(name='builtins', loader=<class '_frozen_importlib.BuiltinImporter'>),
'__build_class__': <built-in function __build_class__>,
'__import__': <built-in function __import__>,
'abs': <built-in function abs>,
'all': <built-in function all>,
'any': <built-in function any>,
'ascii': <built-in function ascii>,
'bin': <built-in function bin>,
'breakpoint': <built-in function breakpoint>,
'callable': <built-in function callable>,
'chr': <built-in function chr>,
'compile': <built-in function compile>,
'delattr': <built-in function delattr>,
'dir': <built-in function dir>,
'divmod': <built-in function divmod>,
'eval': <built-in function eval>,
'exec': <built-in function exec>,
'format': <built-in function format>,
'getattr': <built-in function getattr>,
'globals': <built-in function globals>,
'hasattr': <built-in function hasattr>,
'hash': <built-in function hash>,
'hex': <built-in function hex>,
'id': <built-in function id>,
'input': <built-in function input>,
'isinstance': <built-in function isinstance>,
'issubclass': <built-in function issubclass>,
'iter': <built-in function iter>,
'len': <built-in function len>,
'locals': <built-in function locals>,
'max': <built-in function max>,
'min': <built-in function min>,
'next': <built-in function next>,
'oct': <built-in function oct>,
'ord': <built-in function ord>,
'pow': <built-in function pow>,
'print': <built-in function print>,
'repr': <built-in function repr>,
'round': <built-in function round>,
'setattr': <built-in function setattr>,
'sorted': <built-in function sorted>,
'sum': <built-in function sum>,
'vars': <built-in function vars>,
'None': None, 'Ellipsis': Ellipsis,
'NotImplemented': NotImplemented,
'False': False, 'True': True,
'bool': <class 'bool'>,
'memoryview': <class 'memoryview'>,
'bytearray': <class 'bytearray'>,
'bytes': <class 'bytes'>,
'classmethod': <class 'classmethod'>,
'complex': <class 'complex'>,
'dict': <class 'dict'>,
'enumerate': <class 'enumerate'>,
'filter': <class 'filter'>,
'float': <class 'float'>,
'frozenset': <class 'frozenset'>,
'property': <class 'property'>,
'int': <class 'int'>,
'list': <class 'list'>,
'map': <class 'map'>,
'object': <class 'object'>,
'range': <class 'range'>,
'reversed': <class 'reversed'>,
'set': <class 'set'>,
'slice': <class 'slice'>,
'staticmethod': <class 'staticmethod'>,
'str': <class 'str'>,
'super': <class 'super'>,
'tuple': <class 'tuple'>,
'type': <class 'type'>,
'zip': <class 'zip'>,
'__debug__': True,
'BaseException': <class 'BaseException'>,
'Exception': <class 'Exception'>,
'TypeError': <class 'TypeError'>,
'StopAsyncIteration': <class 'StopAsyncIteration'>,
'StopIteration': <class 'StopIteration'>,
'GeneratorExit': <class 'GeneratorExit'>,
'SystemExit': <class 'SystemExit'>,
'KeyboardInterrupt': <class 'KeyboardInterrupt'>,
'ImportError': <class 'ImportError'>,
'ModuleNotFoundError': <class 'ModuleNotFoundError'>,
'OSError': <class 'OSError'>,
'EnvironmentError': <class 'OSError'>,
'IOError': <class 'OSError'>,
'WindowsError': <class 'OSError'>,
'EOFError': <class 'EOFError'>,
'RuntimeError': <class 'RuntimeError'>,
'RecursionError': <class 'RecursionError'>,
'NotImplementedError': <class 'NotImplementedError'>,
'NameError': <class 'NameError'>,
'UnboundLocalError': <class 'UnboundLocalError'>,
'AttributeError': <class 'AttributeError'>,
'SyntaxError': <class 'SyntaxError'>,
'IndentationError': <class 'IndentationError'>,
'TabError': <class 'TabError'>,
'LookupError': <class 'LookupError'>,
'IndexError': <class 'IndexError'>,
'KeyError': <class 'KeyError'>,
'ValueError': <class 'ValueError'>,
'UnicodeError': <class 'UnicodeError'>,
'UnicodeEncodeError': <class 'UnicodeEncodeError'>,
'UnicodeDecodeError': <class 'UnicodeDecodeError'>,
'UnicodeTranslateError': <class 'UnicodeTranslateError'>,
'AssertionError': <class 'AssertionError'>,
'ArithmeticError': <class 'ArithmeticError'>,
'FloatingPointError': <class 'FloatingPointError'>,
'OverflowError': <class 'OverflowError'>,
'ZeroDivisionError': <class 'ZeroDivisionError'>,
'SystemError': <class 'SystemError'>,
'ReferenceError': <class 'ReferenceError'>,
'MemoryError': <class 'MemoryError'>,
'BufferError': <class 'BufferError'>,
'Warning': <class 'Warning'>,
'UserWarning': <class 'UserWarning'>,
'DeprecationWarning': <class 'DeprecationWarning'>,
'PendingDeprecationWarning': <class 'PendingDeprecationWarning'>,
'SyntaxWarning': <class 'SyntaxWarning'>,
'RuntimeWarning': <class 'RuntimeWarning'>,
'FutureWarning': <class 'FutureWarning'>,
'ImportWarning': <class 'ImportWarning'>,
'UnicodeWarning': <class 'UnicodeWarning'>,
'BytesWarning': <class 'BytesWarning'>,
'ResourceWarning': <class 'ResourceWarning'>,
'ConnectionError': <class 'ConnectionError'>,
'BlockingIOError': <class 'BlockingIOError'>,
'BrokenPipeError': <class 'BrokenPipeError'>,
'ChildProcessError': <class 'ChildProcessError'>,
'ConnectionAbortedError': <class 'ConnectionAbortedError'>,
'ConnectionRefusedError': <class 'ConnectionRefusedError'>,
'ConnectionResetError': <class 'ConnectionResetError'>,
'FileExistsError': <class 'FileExistsError'>,
'FileNotFoundError': <class 'FileNotFoundError'>,
'IsADirectoryError': <class 'IsADirectoryError'>,
'NotADirectoryError': <class 'NotADirectoryError'>,
'InterruptedError': <class 'InterruptedError'>,
'PermissionError': <class 'PermissionError'>,
'ProcessLookupError': <class 'ProcessLookupError'>,
'TimeoutError': <class 'TimeoutError'>,
'open': <built-in function open>,
'quit': Use quit() or Ctrl-Z plus Return to exit,
'exit': Use exit() or Ctrl-Z plus Return to exit,
'copyright': Copyright (c) 2001-2018 Python Software Foundation.
All Rights Reserved.
}

这个字典中包含着python的所有内建功能。我们可以从中找到print()、open()、exit()、False、Bool、dir()等我们常用的内建函数,以及很多异常类。

我们通过使用该字典,可以直接队其中的内建函数进行调用:

global_dict = globals()
builtin_dict = global_dict['__builtins__'].__dict__
builtin_dict['print']("Hello Builtin functions") # 打印 Hello Builtin functions

所以,我们平时在使用内建函数的时候,Python实际上就是在这个字典中查找我们调用的函数名是否存在,存在则调用,不存在则报错。

三、元类

我们知道,类可以创建实例对象。从前面我们可以看出,类实际上也是一种对象,那么类是谁的对象呢??答案是元类。

当我们平时在创建类时:

class Test1():
num1 = 100
num2 = 200 help(Test1)

通过help我们可以看到:

class Test1(builtins.object)
| Data descriptors defined here:
|
| __dict__
| dictionary for instance variables (if defined)
|
| __weakref__
| list of weak references to the object (if defined)
|
| ----------------------------------------------------------------------
| Data and other attributes defined here:
|
| num1 = 100
|
| num2 = 200

在Python中,元类就是type类,我们使用type来创建一个普通类:

Test2 = type('Test2', (), {'num1': 100, 'num2': 200})
help(Test2)

通过help可以看到:

class Test2(builtins.object)
| Data descriptors defined here:
|
| __dict__
| dictionary for instance variables (if defined)
|
| __weakref__
| list of weak references to the object (if defined)
|
| ----------------------------------------------------------------------
| Data and other attributes defined here:
|
| num1 = 100
|
| num2 = 200

我们可以看到Test1和Test2基本是一样的。我们在程序中通过class关键字创建类,实际上和type()创建一个类,效果一样。

在 Test2 = type('Test2', (), {'num1': 100, 'num2': 200}) 中,第一个参数是类名,第二个参数是父类,第三个参数是属性和方法(用字典列出)。

这里注意:我们给一个类取名叫"Test2",那么type的返回值我们也应该用"Test2"来接收(当然也可以用其他的名字),如果不一致的话:

Test222 = type('Test2', (), {'num1': 100, 'num2': 200})
help(Test222)
t = Test222()
# t = Test2() # 报错

但在help中:

class Test2(builtins.object)
| Data descriptors defined here:
|
| __dict__
| dictionary for instance variables (if defined)
|
| __weakref__
| list of weak references to the object (if defined)
|
| ----------------------------------------------------------------------
| Data and other attributes defined here:
|
| num1 = 100
|
| num2 = 200

所以,我们尽量采用一致的名字, 避免出错。

如果一个类继承于Test2:

Test3 = type("Test3", (Test2,), {})

类中的各种成员方法:

def func1(self):
print("This is method func1") @classmethod
def func2(cls):
print("This is class method func2") @staticmethod
def func3():
print("This is static method func3") Test2 = type('Test2', (), {"func1": func1, "func2": func2, "func3": func3})
t = Test2()
t.func1()
Test2.func2()
t.func3()

四、元类什么时候用

元类一般很少使用

我们可以自定义元类,并用于创建普通类:

第一种,用函数来修改属性名(在type运行之前):

def upper_attr(class_name, class_parents, class_attr):
new_attr = {}
for name, value in class_attr.items():
if not name.startswith("__"):
new_attr[name.upper()] = value return type(class_name, class_parents, new_attr) class Foo(object, metaclass=upper_attr):
bar = 'pig' print(hasattr(Foo, "bar")) # 打印 Flase
print(hasattr(Foo, "BAR")) # 打印 True f = Foo()
print(f.BAR) # 打印 pig

upper_attr会修改属性的名称为大写,然后再使用type生成一个Foo类。

第二种,定义一个继承于type的元类来创建Foo类:

class UpperAttrMetaClass(type):
def __new__(cls, class_name, class_parents, class_attr):
print("Here is new")
new_attr = {}
for name, value in class_attr.items():
if not name.startswith("__"):
new_attr[name.upper()] = value return type(class_name, class_parents, new_attr) class Foo(object, metaclass=UpperAttrMetaClass):
def __init__(self, abv):
self.abv = abv
print("Here is init") bar = 'pig' print(hasattr(Foo, "bar")) # 打印 Flase
print(hasattr(Foo, "BAR")) # 打印 True f = Foo()
print(f.BAR) # 打印 pig

UpperAttrMetaClass继承于type,则他就变成了一个元类,由于元类在创建Foo类时会调用__new__函数,所以,我们在__new__函数中做了一些额外的操作。

五、使用__new__实现单例模式(引申)

既然我们可以在类创建对象之前在__new__中做事情,那么我们可以在__new__中判断这个类是否已经存在实例对象,如果存在则直接返回已存在的对象,如果不存在才创建新的对象,这就实现了单例模式。

# -*- coding: utf-8 -*-
import threading class Singleton(object):
_lock = threading.Lock() def __new__(cls, *args, **kwargs):
if not hasattr(Singleton, "_instance"):
with Singleton._lock: # 加锁防止多线程环境中两个线程同时判断到上一行代码为True,同时创建该类的实例
if not hasattr(Singleton, "_instance"):
# 调用object类的__new__方法
Singleton._instance = super(Singleton, cls).__new__(cls, *args, **kwargs)
return Singleton._instance def test(number):
s = Singleton()
print str(number) + ": " + str(id(s)) for i in range(10):
t = threading.Thread(target=test, args=(i, ))
t.start()

[Python之路] 元类(引申 单例模式)的更多相关文章

  1. [转]深刻理解Python中的元类(metaclass)以及元类实现单例模式

    使用元类 深刻理解Python中的元类(metaclass)以及元类实现单例模式 在看一些框架源代码的过程中碰到很多元类的实例,看起来很吃力很晦涩:在看python cookbook中关于元类创建单例 ...

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

    在理解元类之前,你需要先掌握Python中的类.Python中类的概念借鉴于Smalltalk,这显得有些奇特.在大多数编程语言中,类就是一组用来描述如何生成一个对象的代码段.在Python中这一点仍 ...

  3. Python元类(metaclass)以及元类实现单例模式

    这里将一篇写的非常好的文章基本照搬过来吧,这是一篇在Stack overflow上很热的帖子,我看http://blog.jobbole.com/21351/这篇博客对其进行了翻译. 一.理解类也是对 ...

  4. python基础——使用元类

    python基础——使用元类 type() 动态语言和静态语言最大的不同,就是函数和类的定义,不是编译时定义的,而是运行时动态创建的. 比方说我们要定义一个Hello的class,就写一个hello. ...

  5. Python基础:元类

    一.概述 二.经典阐述 三.核心总结 1.类的创建过程 2.元类的使用惯例 四.简单案例 1.默认行为 2.使用元类 五.实践为王 一.概述 Python虽然是多范式的编程语言,但它的数据模型却是 纯 ...

  6. Python中的元类(metaclass)

    推荐+收藏:深刻理解Python中的元类(metaclass) 做一些笔记学习学习: 在大多数编程语言中,类就是用来描述如何生成一个对象的代码段,在Python中类也是一个对象,这个(类)对象自身拥有 ...

  7. 什么是python中的元类

    所属网站分类: python高级 > 面向对象 作者:goodbody 原文链接: http://www.pythonheidong.com/blog/article/11/ 来源:python ...

  8. Python之面向对象元类

    Python之面向对象元类 call方法: class People: def __init__(self,name): self.name=name # def __call__(self, *ar ...

  9. Python 中的元类到底是什么?这篇恐怕是最清楚的了

    类作为对象 在理解元类之前,您需要掌握 Python 的类.Python 从 Smalltalk 语言中借用了一个非常特殊的类概念. 在大多数语言中,类只是描述如何产生对象的代码段.在 Python ...

随机推荐

  1. 【LOJ】#3044. 「ZJOI2019」Minimax 搜索

    LOJ#3044. 「ZJOI2019」Minimax 搜索 一个菜鸡的50pts暴力 设\(dp[u][j]\)表示\(u\)用\(j\)次操作能使得\(u\)的大小改变的方案数 设每个点的初始答案 ...

  2. 对Android应用签名

    Android使用包名作为唯一标识,当在同一台手机安装两个包名相同的应用,后安装的应用就会覆盖前面的应用(签名相同的情况下). 签名有两个主要作用: 1.确定发布者身份.由于应用开发者可以通过使用相同 ...

  3. Linux系列:之软件安装

    1.安装软件 不同的Linux版本可能使用不同的软件管理机制. RPM:使用这类命令进行安装的Linux版本有CentOS. DPKG:使用这类命令进行安装的Linux版本有Debian.Ubuntu ...

  4. #undef取消宏定义

    如果你想定义这个宏那就#define X 如果你不想让你已经#define X的宏在其他地方由于引入这个包含宏定义的.h文件而引起一些编译问题,那你就#undef X掉,就这么简单. 举个简单的例子: ...

  5. Linux就该这么学——初识重定向

    重定向的本质(个人理解) 若是输出重定向,则将命令信息写入到指定文件中; 若是输入重定向,表示将对文件执行一些命令,并将命令结果输出到屏幕. 重定向的5种模式 标准覆盖输入重定向/标准追加输入重定向/ ...

  6. 1-python django的创建

    一.Virtualenv(我的python环境是3.7) 1.虚拟环境创建(针对python版本和django的版本不一致的) 输入 pip install virtuallenv ,看到如下信息就是 ...

  7. Spectral Norm Regularization for Improving the Generalizability of Deep Learning论文笔记

    Spectral Norm Regularization for Improving the Generalizability of Deep Learning论文笔记 2018年12月03日 00: ...

  8. Windows authentication for WCF web services error

    WCF Web服务的Windows身份验证在部署到IIS时,默认网站添加应用程序的方式.浏览运行.svc文件报错. 错误代码: The authentication schemes configure ...

  9. table与json的互转

    json是键值对,在Lua中类型是string 主要运用在table中.表:local t={a="1",b="2",c="3",d=&qu ...

  10. Lua的API函数

    1. 基础库 我们在整个教程中使用了各种主题下的基本库. 下表提供了相关页面的链接,并列出了本Lua教程各部分所涵盖的功能. 编号 库/方法 作用 1 错误处理 包括错误处理函数,如断言, 错误,如L ...