文档章节

Python - 类属性和实例属性

y
 yuerthe9
发布于 2017/04/13 14:46
字数 927
阅读 22
收藏 0

一、实例属性

首先说说差异化最小的实例属性。从代码中直视它们的异同。

JAVA实例属性:

class Book{
	private String name;
    public Book(String name){
        this.name=name;
    }
	public String getName(){
		return this.name;
	}
}

Python实例属性:

class Book:
	def getName(self):
		return self.name

	def __init__(self,name='unnamed'):
        self.name=name

除了语法层面的区别,语义层面是没有任何差异的。这里所描述的“差异”一词,表达的是这样的语境“我明白JAVA中的实例属性,所以Python中的实例属性,我只需要了解语法的区别,就能明白Python的实例属性”

显然,就实例属性来说,二者的区别只在于语法层面。

二、类属性

JAVA代码如下:

class Book{
	public static String paper="宣纸";
}
//为了书写方便,省略main。
Book book=new Book();
System.out.println(book.paper);
Book.paper="竹简";
System.out.println(book.paper);
book.paper="宣纸";
System.out.println(book.paper+"|"+Book.paper);

类属性可以通过类名以及实例名来访问,上述代码通过类名方式修改类属性,查看实例名访问时类属性的变化情况。代码执行结果如下:

>java Book
宣纸
竹简
宣纸|宣纸

通过结果看,JAVA在处理类名和实例名使用类属性时完全一致,尽管类名和实例名不是一个逻辑层次的概念,所以才会有尴尬的提示——建议使用类名来访问类属性。

这种处理方式会让人觉得“很随意”,但是的确降低了程序员的理解成本。

Python代码如下:

class Book:
	paper=u'宣纸'

book=Book()
print book.paper
Book.paper=u'竹简'
print book.paper
book.paper=u'宣纸'
print book.paper,Book.paper

运行结果如下:

>python book.py
宣纸
竹简
宣纸 竹简

对比JAVA的输出,最大的区别在于——实例名操作了类属性之后,结果出现天壤之别。

为什么会是这样?

  1. python的属性查找规则造成了,实例名也可以访问类属性的假象。当调用book.paper时,python会向上查找属性,也就是说最终显示出来的是Book.paper
  2. 通过实例名设置一个不存在的属性时,python会动态创建这个属性。这个属性既然是真实存在的,那么就和Book.paper没有任何关系,各自存储各自的数据,所以不一样的变化就出现了。

这么“诡异”的现象把理由讲出来后,你会发现这是一种很“自然”的处理方式。代价当然是增加了理解的难度。

通过这个“好玩”的东东,衍生了一个设计模式——Borg,根据上述的说明,它非常容易理解。

三、Borg设计模式

代码如下(摘自github):

class Borg(object):
    __state_pool = {}
    def __init__(self):
        self.__dict__ = self.__state_pool #这是秘密的关键,所有实例的所有属性将全部共享。
        self.state = 'Init'
    def __str__(self):
        return self.state
class YourBorg(Borg):
    pass

if __name__ == '__main__':
    rm1 = Borg()
    rm2 = Borg()
    rm1.state = 'Idle'
    rm2.state = 'Running'
    print('rm1: {0}'.format(rm1))
    print('rm2: {0}'.format(rm2))
    rm2.state = 'Zombie'
    print('rm1: {0}'.format(rm1))
    print('rm2: {0}'.format(rm2))
    print('rm1 id: {0}'.format(id(rm1)))
    print('rm2 id: {0}'.format(id(rm2)))
    rm3 = YourBorg()
    print('rm1: {0}'.format(rm1))
    print('rm2: {0}'.format(rm2))
    print('rm3: {0}'.format(rm3))

执行效果如你所想:

>python 01.py
rm1: Running
rm2: Running
rm1: Zombie
rm2: Zombie
rm1 id: 31013576
rm2 id: 40287424
rm1: Init
rm2: Init
rm3: Init

Borg实现了所有实例的所有属性的共享——单态池!我想这应该是非常贴切的一个名字。

为任意一个实例添加一个属性,其他所有实例都可以共享访问。

复制代码,修改后试试效果。

© 著作权归作者所有

y
粉丝 0
博文 1
码字总数 927
作品 0
私信 提问
关于Python类属性与实例属性的讨论

标题名字有点长。 之所以想写这个文章是因为碰巧看到网上一篇关于Pyhon中类属性及实例属性区别的帖子。因为我之前也被这个问题困扰过,今天碰巧看到了这篇帖子,发现帖子的作者只是描述了现象...

_Zhao
2018/08/27
0
0
Python3 与 C# 面向对象之~封装

最新彩版:https://www.cnblogs.com/dotnetcrazy/p/9202988.html 在线编程:https://mybinder.org/v2/gh/lotapp/BaseCode/master 在线预览:http://github.lesschina.com/python/base/oop/1......

毒逆天
2018/06/20
0
0
Python 类属性与实例属性的关联

类属性是属于一个类的变量,就像是C++中类的静态成员变量,你只需将该属性定义在所有方法的作用域外,即为类属性,但一般是紧跟在类名后面,类属性为所有实例所共有,你可以通过 类名.属性 ...

突然帅了
2015/04/26
0
1
python之类属性和实例对象属性

python中的实例对象属性(Instance Attributes)就是跟这个对象绑定的简单的数据而已。实例对象属性一般在init函数中初始化,但是在其它方法中也是可以随意添加新的属性。 class Foo(object):...

fanzc
2012/11/15
0
0
Python中的类属性和实例属性以及静态方法和类方法

可以在Python的类定义中直接添加静态变量,如下例中的foo。此属性属于类C,可以直接通过C.foo访问,而无需实例化它。而实例属性则只存在于对象的实例中,这也就意味着,每一个不同的实例都有...

lionets
2013/10/23
0
0

没有更多内容

加载失败,请刷新页面

加载更多

【AI实战】手把手教你深度学习文字识别(文字检测篇:基于MSER, CTPN, SegLink, EAST等方法)

文字检测是文字识别过程中的一个非常重要的环节,文字检测的主要目标是将图片中的文字区域位置检测出来,以便于进行后面的文字识别,只有找到了文本所在区域,才能对其内容进行识别。 文字检...

雪饼
今天
7
0
思维导图XMind 8 Pro 绿化方法(附序列号)

按部就班: Step 1 -全新下载最新版本的 Xmind 8(注必须是英文官方的版本,中文代{过}{滤}理网站的版本修改过,无法使用pj); Step 2 -安装完毕后,点击文末的下载按钮下载pj补丁文件包,将...

一只小青蛙
今天
10
0
数据结构(ER数据库)设计规范

表命名规范 表命名的规则分为3个层级,层级之间通过_分割,例如b_r_identity、d_l_identity。规约为: [leavel]_[type]_[name] [leavel] 表示数据库表的层级和功能,分为: s:业务无关的系统...

随风溜达的向日葵
今天
6
0
阿里Sentinel控制台源码修改-对接Apollo规则持久化

https://github.com/alibaba/Sentinel/wiki/%E5%9C%A8%E7%94%9F%E4%BA%A7%E7%8E%AF%E5%A2%83%E4%B8%AD%E4%BD%BF%E7%94%A8-Sentinel 动态规则扩展 https://github.com/alibaba/Sentinel/wiki......

jxlgzwh
昨天
9
0
在Linux系统中创建SSH服务器别名

如果你经常通过 SSH 访问许多不同的远程系统,这个技巧将为你节省一些时间。你可以通过 SSH 为频繁访问的系统创建 SSH 别名,这样你就不必记住所有不同的用户名、主机名、SSH 端口号和 IP 地...

老孟的Linux私房菜
昨天
13
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部