Python: 浅淡Python中的属性(property)
起源:
项目过程中需要研究youtube_dl这个开源组件,翻阅其中对类的使用,对比c#及Delphi中实现,感觉Python属性机制挺有意思。
区别与高级编程语言之单一入口,在类之属性这一方面,它随意的太多,以致于习惯了高级语言的严谨,对如此随意心里倒是有些不安。
也难怪,因为其数据类型弱限制性,往往一个函数返回了一个结果,追溯此返回值类型,有时需要费上许多工夫!
我不是随意的人,但随意起来我还真不是人,用在此处,颇为贴切:b
属性,是对事物某种特性的抽象,面向对象编程中一个重要概念;区别于字段,它通常表示为字段的扩展,加以访问与设置保护机制。
比如动物,它的颜色、重量,都可以说是它的属性,此篇以一动物类来做例子,浅探其中属性机制。
1、新式类和经典类(New-style classes)
Python 2.x默认类为经典类,而对属性支持完全者为新式类,其区别请自行度娘。
Python 3.x默认即为新式类,不必显式继承于object类。
如下面代码类之定义:
#此为经典类
class AnimalClassic:
pass #此为新式类,Python 2.2始支持
class Animal(object):
pass
虽一object差别,但其内在机制,改变颇多。略一窥之,大体如下:
>>>print dir(AnimalClassic)
返回:
['__doc__', '__module__']
>>>print dir(Animal)
返回:
['__class__', '__delattr__', '__dict__', '__doc__', '__format__', '__getattribute__', '__hash__', '__init__', '__module__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__']
由此可知,其加入了诸多面向对象的支持;此节属性知识,亦基于新式类构建。所以诸君用Python 2.x做开发,写面向对象代码时,切记要继承于object类
2、随意的属性
通常,我们这样定义属性:
class Animal(object):
def __init__(self, name, age):
self.name = name
self.age = age
即在实例初始化时,__init__函数中赋值,其中值可为实例访问:
a = Animal('black dog', 3)
print 'Name:', a.name
print 'Age:', a.age
a.color = 'Black'
print 'Color:', a.color
结果为:
Name: black dog
Age: 3
Color: Black
看到了吧?运行期,能动态为实例添加属性,比如color。但此方法所添加,只能作用于此实例,而无影响于类
怎么限制它?
用__slots__这个东西。比如,__slots__ = ['name', 'age'],则类只能添加这两个属性,蛋疼,不好用
如果想要在运行期给类添加属性,要用到MethodType这东西,例如:
def set_color(self, color):
self.color = color
Animal.set_color = MethodType(set_color, None, Animal) a1 = Animal('yellow dog', 3)
a1.set_color('Yellow')
print a1.color
……喔,有点凌乱,还是不好用!或者说,不好记,心里没谱儿。
3、@property(推荐)
习惯了高级语言的严谨,总想对属性加以访问控制,相对安全些,比如直接在__init__中定义公用属性,从封装性来说,它是不好的写法。
属性之访问,它亦有机制,其一便是@propery关键字。用此关键字,其获取、设置函数,须与属性名一致。
@property可以把一个实例方法变成其同名属性,以支持.号访问,它亦可标记设置限制,加以规范,如下代码:
class Animal(object):
def __init__(self, name, age):
self._name = name
self._age = age
self._color = 'Black' @property
def name(self):
return self._name @name.setter
def name(self, value):
if isinstance(value, basestring):
self._name = value
else:
self._name = 'No name' @property
def age(self):
return self._age @age.setter
def age(self, value):
if value > 0 and value < 100:
self._age = value
else:
self._age = 0
# print 'invalid age value.' @property
def color(self):
return self._color @color.setter
def color(self, value):
self._color = value; a = Animal('black dog', 3)
a.name = 'white dog'
a.age = 300
print 'Name:', a.name
print 'Age:', a.age
这样在设定值时候,总算有个判断取舍,是不是好一些?
私有变量以_开头,是种编码约定,当然也可以直接访问它。
不过既如此写,直接访问是不推荐的。
若真要为私有变量,则加双下划线,比如__name,也一样阻止不了访问,但让我们知道,它不想被直接用到,如下代码:
class Animal(object):
def __init__(self, name):
self.__name = name a = Animal('black dog')
print a._Animal__name
这种写法当真好奇怪!
引廖雪峰言:总的来说就是,Python本身没有任何机制阻止你干坏事,一切全靠自觉。自觉靠谱么?不见得,但愿做人靠谱。
4、property函数
它以一个函数形式,定义一个属性,与@property实现原理类似,或者就是它的的变异用法。
其原型为:
property(fget=None, fset=None, fdel=None, doc=None)
譬如上面Animal类,其可用此改为:
class Animal(object):
def __init__(self, name, age):
self._name = name
self._age = age
self._color = 'Black' def get_name(self):
return self._name def set_name(self, value):
if isinstance(value, basestring):
self._name = value
else:
self._name = 'No name' name = property(fget=get_name, fset=set_name, fdel=None, doc='name of an animal') def get_age(self):
return self._age def set_age(self, value):
if value > 0 and value < 100:
self._age = value
else:
self._age = 0
# print 'invalid age value.' age = property(fget=get_age, fset=set_age, fdel=None, doc='name of an animal') a = Animal('black dog', 3)
a.name = 'white dog'
a.age = 3
print 'Name:', a.name
print Animal.name.__doc__
print 'Age:', a.age
其输出结果一样,看来只是写法不同。
后记:
由此可见,Python作为一种解释型语言,其简单易用,但其随意性也大。如此属性篇,也只是阐述其中一点,其它方面须在使用中去学习留意。
习惯了语法严谨,编码亦请以Pythonic的风格去编写,python实在没有多大限制,只要正确计算机都能够编译,代码风格是给人看的,优雅总比零乱好。
如上面几种属性写法,我尤其喜欢@property方式,相对简洁一些。而此写法,亦为youtube-dl推荐样式,着实不错。
参考资料:
Built-in Functions
Python基础:新式类的属性访问
Python深入03 对象的属性
Python: 浅淡Python中的属性(property)的更多相关文章
- 浅谈CSS3中display属性的Flex布局
浅谈CSS3中display属性的Flex布局 最近在学习微信小程序,在设计首页布局的时候,新认识了一种布局方式display:flex 1 .container { 2 display: fle ...
- 浅谈Vue中计算属性(computed)和方法(methods)的差别
浅谈Vue中计算属性(computed)和方法(methods)的差别 源码地址 methods方法和computed计算属性,两种方式的最终结果确实是完全相同 计算属性是基于它们的响应式依赖进行缓存 ...
- Python - 浅谈Python的编译与反编译
1 - Python编译过程涉及的文件 py 源代码文件,由python.exe解释,可在控制台下运行,可用文本编辑器进行编辑: pyc 源代码文件经过编译后生成的二进制文件,无法用文本编辑器进行编辑 ...
- 浅谈Vue中计算属性computed的实现原理
虽然目前的技术栈已由Vue转到了React,但从之前使用Vue开发的多个项目实际经历来看还是非常愉悦的,Vue文档清晰规范,api设计简洁高效,对前端开发人员友好,上手快,甚至个人认为在很多场景使用V ...
- C#中的属性-Property
C#的属性一直都有用,但具体了解的不是很深,而且一些注意事项也没有太在意过,糊里糊涂的用着.这两天看了C#的书专门学习了一下属性,这才知道,原来属性也有这么多东西~ ~今天记录一下,算是对学习的一个检 ...
- 浅淡python中的with,上下文管理器
例子一 首先来看一段代码: class Foo(object): def __init__(self): print('实例化一个对象') def __enter__(self): print('进入 ...
- Python高级语法-对象实例对象属性-Property总结(4.6.2)
@ 目录 1.说明 2.代码 关于作者 1.说明 property属性,返回的是值 不是callable的,也就是不能使用方法来调用 只能传入self,不能传入其他 用处,能返回局部数据,比如当分页的 ...
- Objective-C 在Categroy中创建属性(Property)
Objective-c中category是不能直接创建属性的,这时候我们要用到Objc的runtime来实现 用到的方法有两个 一个是get方法 一个set方法 //get方法objc_getAsso ...
- 【整理】Object-C中的属性(Property)的Setter:assign,copy,retain,weak,strong之间的区别和联系
iOS编程过程中,经常看到一些属性前面有些修饰符,比如copy,retain等. 这些关键字,是Object-C语言中,对于Property的setter. Mac官网: The Objective- ...
随机推荐
- springmvc启动时报错:找不到类ContextLoaderListener:java.lang.ClassNotFoundException: org.springframework.web.context.ContextLoaderListener
严重: Error configuring application listener of class org.springframework.web.context.ContextLoaderLis ...
- js修改table中Td的值(定义td的单击事件)
/* 页面装载时,为每个td增加单击事件,这样,就可以不用对每个页面进行更改. 添加单击事件属性.此处不可使用setAttribute方法. */ onclick=AddObjOfText; 单击事件 ...
- 应用SharedPreference保存程序的配置信息
SharedPreference: 1.用来保存应用程序的配置信息的XML文件,内部的数据形式为键值对 2.一般存在于/data/data/<包名>shared_prefs目录下 3.该对 ...
- Eclipse编译Android项目时出现的问题:Android requires compiler compliance level 5.0 or 6.0. Found '1.8' instead.
Consle: Android requires compiler compliance level 5.0 or 6.0. Found '1.8' instead. Please use Andro ...
- 面图层拓扑检查和错误自动修改—ArcGIS案例学习笔记
面图层拓扑检查和错误自动修改-ArcGIS案例学习笔记 联系方式:谢老师,135_4855_4328,xiexiaokui#139.com 数据源: gis_ex10\ex01\parcel.shp, ...
- yum源制作
CentOS7 同步远程镜像 搭建本地yum服务器同步CentOS镜像站点的数据到本地服务器,使用nginx实现http服务向局域网内的其他机器提供yum服务,解决内网yum安装软件的问题. 一.前提 ...
- python小数据池概念以及具体范围
= 赋值符号: == 比较值是否相等: is 比较,比较的是内存地址 ID(内容) 数字,字符串的小数据池 小数据池现象产生的原因,作用: 为了节省内存空间. &l ...
- js原型、原型链、作用链、闭包全解
https://www.2cto.com/kf/201711/698876.html [对象.变量] 一个对象就是一个类,可以理解为一个物体的标准化定义.它不是一个具体的实物,只是一个标准.而通过对象 ...
- Electrom will-download pause function
1.code from github url-link: https://github.com/electron/electron/issues/7712 // to store downloadIt ...
- Linux命令_2
P42 远程管理 命令 目标 关机/重启 shutdown 查看或配置网卡信息 ifconfig ping 远程登录和复制文件 ssh scp 01.关机/重启 命令: shutdown 选项 时 ...