1 新式类与旧式类

新式类拥有经典类的全部特性之外,还有一些新的特性,比如 __init__发生变化,新增了静态方法__new__,python3目前都采用新式类,新式类是广度优先,旧式类是深度优先

#新式类
class C(object):
pass
#经典类
class B:
pass
(1)内置的object对象

1. __new__,__init__方法
这两个方法是用来创建object的子类对象,静态方法__new__()用来创建类的实例,然后再调用
__init__()来初始化实例。 2. __delattr__, __getattribute__, __setattr__方法
对象使用这些方法来处理属性的访问 3. __hash__, __repr__, __str__方法
print(someobj)会调用someobj.__str__(), 如果__str__没有定义,则会调用someobj.__repr__(), __str__()和__repr__()的区别:
默认的实现是没有任何作用的
__repr__的目标是对象信息唯一性
__str__的目标是对象信息的可读性
容器对象的__str__一般使用的是对象元素的__repr__
如果重新定义了__repr__,而没有定义__str__,则默认调用__str__时,调用的是__repr__
也就是说好的编程习惯是每一个类都需要重写一个__repr__方法,用于提供对象的可读信息,
而重写__str__方法是可选的。实现__str__方法,一般是需要更加好看的打印效果,比如你要制作
一个报表的时候等。
(2)类的方法

静态方法

静态方法可以被类或者实例调用,它没有常规方法的行为(比如绑定,非绑定,默认的第一个self参数),当有一
堆函数仅仅是为了一个类写的时候,采用静态方法声明在类的内部,可以提供行为上的一致性。
使用装饰符@staticmethod进行创建

类方法

也是可以通过类和它的实例进行调用,不过它是有默认第一个参数,叫做是类对象,一般被
命名为cls,当然你也可以命名为其它名字,这样就你可以调用类对象的一些操作,
代码如下,使用装饰符@classmethod创建:

新式类(new-style-class)

__init__方法 : 类的初始化方法

__new__静态方法

新式类都有一个__new__的静态方法,它的原型是object.__new__(cls[, ...])

cls是一个类对象,当你调用C(*args, **kargs)来创建一个类C的实例时,python的内部调用是

C.__new__(C, *args, **kargs),然后返回值是类C的实例c,在确认

c是C的实例后,python再调用C.__init__(c, *args, **kargs)来初始化实例c。

所以调用一个实例c = C(2),实际执行的代码为:

c = C.__new__(C, 2)
if isinstance(c, C):
C.__init__(c, 23)#__init__第一个参数要为实例对象 class Singleton(object):
_singletons = {}
def __new__(cls):
if not cls._singletons.has_key(cls): #若还没有任何实例
cls._singletons[cls] = object.__new__(cls) #生成一个实例
return cls._singletons[cls] #返回这个实例
a = Singleton()
b = Singleton()
id(a) #35966666
id(b) #35966666
#注:单例模式 ,两个实例指向同一个内存地址
(3)新式类实例

新式类的实例也具有新的特性。比如它拥有Property功能,该功能会对属性的访问方式产生影响;还有__slots__新属性,该属性会对生成子类实例产生影响;还添加了一个新的方法__getattribute__,比原有的__getattr__更加通用。

__slots__属性

通常每一个实例x都会有一个__dict__属性,用来记录实例中所有的属性和方法,也是通过这个字典,

可以让实例绑定任意的属性。而__slots__属性作用就是,当类C有比较少的变量,而且拥有__slots__属性时,

类C的实例 就没有__dict__属性,而是把变量的值存在一个固定的地方。如果试图访问一个__slots__中没有

的属性,实例就会报错。这样操作有什么好处呢?__slots__属性虽然令实例失去了绑定任意属性的便利,

但是因为每一个实例没有__dict__属性,却能有效节省每一个实例的内存消耗,有利于生成小而精

干的实例。

定义__slots__属性

class A(object):
def __init__(self):
self.x = 1
self.y = 2
__slots__ = ('x','y')
a = A()
a.z = 3
a.u = 4 #都会报错,不能对实例新增属性,__dict__字典集没有任何改变 class A(object):
def __init__(self):
self.x = 1
self.y = 2
a = A()
a.x = 3 #不会报错,在__dict__字典字典集会新增'x'属性

使用时__slots__时需要注意的几点:

1.  当一个类的父类没有定义__slots__属性,父类中的__dict__属性总是可以访问到的,所以只在子
类中定义__slots__属性,而不在父类中定义是没有意义的。
2. 如果定义了__slots__属性,还是想在之后添加新的变量,就需要把'__dict__'字符串添加到__slots__的
元组里。
3. 定义了__slots__属性,还会消失的一个属性是__weakref__,这样就不支持实例的weak reference,
如果还是想用这个功能,同样,可以把'__weakref__'字符串添加到元组里。
4. __slots__功能是通过descriptor实现的,会为每一个变量创建一个descriptor。
5. __slots__的功能只影响定义它的类,因此,子类需要重新定义__slots__才能有它的功能。
__getattribute__方法

对新式类的实例来说,所有属性和方法的访问操作都是通过__getattribute__完成,这是由object基类实现的。如果有特殊的要求,可以重载__getattribute__方法.

2 __init____new__区别

  1. __new__是一个静态方法,而__init__是一个实例方法.
  2. __new__方法会返回一个创建的实例,而__init__什么都不返回.
  3. 只有在__new__返回一个cls的实例时后面的__init__才能被调用.
  4. 当创建一个新实例时调用__new__,初始化一个实例时用__init__.

__metaclass__是创建类时起作用.所以我们可以分别使用__metaclass__,__new____init__来分别在类创建,实例创建和实例初始化的时候做一些操作

3 单例模式

​ 单例模式是一种常用的软件设计模式。在它的核心结构中只包含一个被称为单例类的特殊类。通过单例模式可以保证系统中一个类只有一个实例而且该实例易于外界访问,从而方便对实例个数的控制并节约系统资源,系统中存在多个该类的实例对象,而这样会严重浪费内存资源 如果希望在系统中某个类的对象只能存在一个,单例模式是最好的解决方案。

__new__()__init__()之前被调用,用于生成实例对象。利用这个方法和类的属性的特点可以实现设计模式的单例模式。单例模式是指创建唯一对象,单例模式设计的类只能实例一次

一般python中可以采用以下方法实现单例模式

  • 使用模块(import导入)
  • 使用 __new__
  • 使用装饰器(decorator)
  • 使用元类(metaclass)

(1)使用__new__方法

class Singleton(object):
def __new__(cls, *args, **kw):
if not hasattr(cls, '_instance'): #如果该类是否含有实例
orig = super(Singleton, cls)
cls._instance = orig.__new__(cls, *args, **kw)
return cls._instance class MyClass(Singleton):
a = 1 #如果 cls._instance 为 None 则创建实例,否则直接返回 cls._instance。

(2)共享属性(使用metaclass)

元类(metaclass)可以控制类的创建过程,它主要做三件事:

  • 拦截类的创建
  • 修改类的定义
  • 返回修改后的类

创建实例时把所有实例的__dict__指向同一个字典,这样它们具有相同的属性和方法.

class Borg(object):
_state = {}
def __new__(cls, *args, **kw):
ob = super(Borg, cls).__new__(cls, *args, **kw)
ob.__dict__ = cls._state
return ob class MyClass2(Borg):
a = 1

(3) 装饰器版本

def singleton(cls):
instances = {}
def getinstance(*args, **kw):
if cls not in instances:
instances[cls] = cls(*args, **kw)
return instances[cls]
return getinstance @singleton
class MyClass:
...

(4) import 方法(使用模块)

作为python的模块是天然的单例模式

# mysingleton.py
class My_Singleton(object):
def foo(self):
pass
my_singleton = My_Singleton() # to use
from mysingleton import my_singleton #将类进行导入使用
my_singleton.foo()

4 Python作用域

python的作用域分全局和局部,python变量的作用域分为以下四类:

L(local) 局部作用域

E(Enclosing) 闭包函数外的函数中

G(Global) 全局作用域

B(Built-in) 内建作用域

(1) 局部作用域

在了解局部作用域之前,先了解下块级作用域的概念

#块级作用域
if 1 == 1:
name = "lol"
print(name) for i in range(10):
age = i
print(age) #输出:
C:/Users/L/PycharmProjects/s14/preview/Day8/作用域/test.py
lol
9

可以发现python代码运行ok,为什么外部可以调用内部的变量呢? 因为在python中没有块级作用域的概念,代码块里的变量,外部可以调用,所以可运行成功, 也就是说,类似条件判断(if…..else)、循环语句(for x in data)、异常捕捉(try…catch)等的变量是可以全局使用的 .但是不区分作用域明显是不行的,因此python引入局部作用域

#局部作用域
def func():
name = "lol"
func() #调用函数
print(name)
#输出
Traceback (most recent call last):
File "C:/Users/L/PycharmProjects/s14/preview/Day8/作用域/test.py", line 23, in <module>
print(name)
NameError: name 'name' is not defined

即使执行了一下函数,name的作用域也只是在函数内部,外部依然无法进行调用 ,因此函数可以产生局部作用域,在python中模块(module),类(class)、函数(def、lambda)会产生新的作用域 .

(2) 作用域链

#作用域链
name = "张三"
def func1():
name = "李四"
def func2():
name = "王五"
print(name)
func2()
func1()
#输出
"王五"

func1()调用函数执行变量赋值操作,当调用func2()时 , print(name)中name属性会先从局部作用域开始寻找,由内至外,最先找到的当然是 '王五'.Python中有作用域链,变量会由内到外找,先去自己作用域去找,自己没有再去上级去找,直到找不到报错 .

(3) 全局作用域与内建作用域

x = int(2.9)  # 内建作用域
num = 0 # 全局作用域
def outer():
num2 = 1 # 闭包函数外的函数中
def inner():
num3 = 2 # 局部作用域

(4) global关键字

全局变量是指在函数外的变量,可以在程序全局使用,局部变量是指定义在函数内的变量,只能在函数内被声明使用若内部作用域的想要修改外部作用域的变量,就要使用global关键字

a = 100

def demo():
global a
a = 123
print(a)
demo()
print(a) #运行结果是
123
123

本来运行结果应该是123,100,但是因为global声明a为全局作用域,因此在执行赋值后的a指向123,因此两次打印的都是123.

总结下:

​ Python 中,一个变量的作用域总是由在代码中被赋值的地方所决定的。当 Python 遇到一个变量的话他会按照这样的顺序进行搜索:本地作用域(Local)→当前作用域被嵌入的本地作用域(Enclosing locals)→全局/模块作用域(Global)→内置作用域(Built-in)

Python新式类 单例模式与作用域(四)的更多相关文章

  1. Python新式类和经典类的区别

    @Python新式类和经典类的区别 class ClassicClass(): pass class NewStyleClass(object): pass x1 = ClassicClass() x ...

  2. Python新式类与经典类的区别

    1.新式类与经典类 在Python 2及以前的版本中,由任意内置类型派生出的类(只要一个内置类型位于类树的某个位置),都属于“新式类”,都会获得所有“新式类”的特性:反之,即不由任意内置类型派生出的类 ...

  3. Python新式类继承的C3算法

    在Python的新式类中,方法解析顺序并非是广度优先的算法,而是采用C3算法,只是在某些情况下,C3算法的结果恰巧符合广度优先算法的结果. 可以通过代码来验证下: class NewStyleClas ...

  4. python新式类与旧式类

    python2.X是经典类[旧式类]: 是以深度优先[] 但是在Python2.x中,默认都是经典类,只有显式继承了object才是新式类,即:class Person(object):pass 新式 ...

  5. Python 新式类与经典类

    新式类,经典类 查询匹配 广度查询 横着对每个类进行查询 深度查询 无视平级类,直接寻找下级类 #python 3.0 #新式类 广度查询 #经典类 广度查询 #python 2.0 #新式类 广度查 ...

  6. 【Python】Python 新式类介绍

    本文转载自:kaka_ace's blog 我们使用 Python 开发时, 会遇到 class A 和 class A(object) 的写法, 这在 Python2 里是有概念上和功能上的区别, ...

  7. Python新式类与经典类(旧式类)的区别

    看写poc的时候看到的,思考了半天,现在解决了 转载自http://blog.csdn.net/zimou5581/article/details/53053775 Python中类分两种:旧式类和新 ...

  8. Python新式类和旧式类的区别

    新式类是为了统一**而在2.2中开始引入的. 代码讲解 上面的例子比较明白的说明了问题. B是定义的新式类.那么输入b的时候,不论是type(b),还是b.__class__都是输出的<clas ...

  9. python 新式类的 __getattribute__

    这个方法定义在object中,所以所有的新式类都继承有该方法,所有的新式类的实例在获取属性value的时候都会调用该方法,为了验证这一结论,我们重写一下该方法: class C(object): a ...

随机推荐

  1. flume将数据发送到kafka、hdfs、hive、http、netcat等模式的使用总结

    1.source为http模式,sink为logger模式,将数据在控制台打印出来. conf配置文件如下: # Name the components on this agent a1.source ...

  2. Web 前端 中高难度问题(希望看完之后的你可以拿到Offer^v^)

    1. 解释 event loop Javascript是单线程的,所有的同步任务都会在主线程中执行. 主线程之外,还有一个任务队列.每当一个异步任务有结果了,就往任务队列里塞一个事件. 当主线程中的任 ...

  3. 转 禁用HAIP,cluster_interconnects配错了集群无法启动

    简介: 在Oracle 11.2.0.2之前,私网的冗余一般是通过在OS上做网卡绑定(如Bond等)来实现的,从Oracle 11.2.0.2版本开始推出HAIP(Highly Available V ...

  4. TCP/IP协议分为哪四层,具体作用是什么。

    TCP/IP通讯协议采用了4层的层级结构,每一层都呼叫它的下一层所提供的网络来完成自己的需求.这4层分别为: 应用层:应用程序间沟通的层,如简单电子邮件传输(SMTP).文件传输协议(FTP).网络远 ...

  5. c#实现常用排序算法

    让我们先看一看常用排序算法的效率对比 接着请看代码和注释~ using System; using System.Collections.Generic; using System.Linq; usi ...

  6. TT8509: PL/SQL execution terminated; PLSQL_TIMEOUT exceeded

    TT8509: PL/SQL execution terminated; PLSQL_TIMEOUT exceeded plsql_timeout连接超时,解决办法: ODBC pl/sql选项卡 修 ...

  7. 简单的CSS3鼠标滑过图片标题和遮罩层动画特效

    此文转自:http://www.cnblogs.com/w2bc/p/5735300.html,仅供本人学习参考,版权归原作者所有!   这是一款使用CSS3制作的简单的鼠标滑过图片标题和遮罩层动画特 ...

  8. 怎么理解impala(impala工作原理是什么)

    下面给大家介绍怎么理解impala,impala工作原理是什么. Impala是hadoop上交互式MPP SQL引擎, 也是目前性能最好的开源SQL-on-hadoop方案. 如下图所示, impa ...

  9. 简介SWT Jface

    可以使用标准窗口小部件工具箱(Standard Widget Toolkit,SWT)和 JFace 库来开发用于 Eclipse 环境的图形用户界面,而且还可以将它们用于开发单独的 GUI 本机应用 ...

  10. SEH结构

    首先有几点问题 1.在后文中看到的PE的节中的配置信息表Load configuration是对SEH回调函数的注册,那么Exception Table是加载的什么信息. 2.什么时候走进系统异常,什 ...