Python 进阶_OOP 面向对象编程_类属性和方法
目录
类属性
在理解类属性之前要先搞清楚 实例属性 和 函数属性 之间的区别:
1. 实例属性:指的是实例化类对象的属性,需要在类中使用 self 关键字来将其和实例化对象绑定的属性。
2. 函数属性:指的是定义在函数体内的属性,其可以是实例属性,也可以是类属性。
3. 类属性:是一个与实例无关的属性,比起实例属性而言,它更加的 静态,当定义在类方法中时,并不会因为方法调用的完毕而被回收。类属性,在类定义中直接指定,无须 self 关键字,所以也只能在类中使用。所以类属性只能通过类的成员方法或类调用来更新。
静态:表示一个对所有实例而言都是相对固定的值
NOTE:类属型也称之为 静态属性,当我们定义一个类静态属性时,无须实例化对象,直接可以通过类来调用该属性,直到这个类被回收为止。如果在 Java 中,你需要使用 static 来指定。当然类的实例化对象也可以通过句点标识符来调用和更改,但此时的更改并不会影响原来的类静态属性。
EXAMPLE:
In [48]: class AClass(object):
...: LOG = 'Define a class'
...:
In [49]: AClass.LOG
Out[49]: 'Define a class'
In [50]: a_object = AClass()
In [51]: a_object.LOG
Out[51]: 'Define a class'
In [52]: a_object.LOG = 'Call the static attribute.'
In [53]: a_object.LOG
Out[53]: 'Call the static attribute.'
In [54]: AClass.LOG
Out[54]: 'Define a class'
通过这个例子可以看出类属性的调用可以完全无需实例化一个类对象。
调用类属性
注意:在类定义的函数体中调用类属性,需要通过 类名结合句点标识符 的方式来调用,否则会出发 NameError
In [93]: class AClass(object):
...: LOG = 'Define a class'
...: def my_func(self):
...: print ''.join(['log: ', AClass.LOG])
# 函数体中
...: print ''.join(['log is: ', LOG])
# 类体中
...:
...:
log is: Define a class
In [91]: a_object = AClass()
In [92]: a_object.my_func()
log: Define a class
查看类属性
Python 为此提供了两个方法:
- 通过 dir() 来查看类属性
In [55]: dir(AClass)
Out[55]:
['LOG',
'__class__',
'__delattr__',
'__dict__',
'__doc__',
'__format__',
'__getattribute__',
'__hash__',
'__init__',
'__module__',
'__new__',
'__reduce__',
'__reduce_ex__',
'__repr__',
'__setattr__',
'__sizeof__',
'__str__',
'__subclasshook__',
'__weakref__']
class.__dict__
来查看类属性,等效于vars(AClass)
In [83]: AClass.__dict__
Out[83]:
dict_proxy({'LOG': 'Define a class',
'__dict__': <attribute '__dict__' of 'AClass' objects>,
'__doc__': None,
'__module__': '__main__',
'__weakref__': <attribute '__weakref__' of 'AClass' objects>})
两者的区别在于:前者仅能查看类属性的列表,后者可以查看类属性的键值对字典。
特殊的类属性
从上述的例子可以看出类中处理我们定义的 LOG 属性之外还有很多以双下划线 “__” 开头和结尾的属性,这些属性都是 Python 的特殊属性。
特殊属性 | 作用 |
---|---|
C.name | 类的名字(String) |
C.doc | 类的文档(String) |
C.bases | 子类的父类元组(Tuple) |
C.dict | 类的属性字典(Dict) |
C.module | 类所有的模块名称 |
instance.class | 类实例对象的类名称 |
NOTE:其中 __dict__
是一个包含了类属性的字典,方 Python 解析器访问一个类属性时,就会在这个字典中搜索。如果在该类的字典中没有搜索到,那么就会到该类的父类的属性字典中搜索。这样的话就能够将不同类之间的属性名隔离开来,在子类中对属性字典的修改并不会影响到父类的属性字典。
类方法
类方法就最基本的特征就是需要传递一个 class 对象作为方式的实参。
真·构造器 __new__()
与 __init__()
相比 __new__()
才是真正的构造器,实际上,在 Python 解析器中是先调用了 __new__()
生成一个实例,再将该实例对象传入 __init__()
实现初始化操作。但 __new__()
很少需要我们去重载,一般只有在派生了不可变类型的子类后需要重载,EG. 派生 String/Int/Tuple 等
为什么说 __new__()
是真·构造器呢?
因为这个特殊的类方法是真的返回了一个类的实例对象,而不像 __init__()
是传入了一个实例化对象。
EXAMPLE:不可表类型的派生
class RoundFloat(float):
def __new__(cls, val):
return float.__new__(cls, round(val, 2)) #因为 __new__ 是一个类方法,所以我们要显式的传递一个类对象
类 RoundFloat 是类 float 的子类,我们通过重载父类的 __new__()
构造器来定制一个新的不可变类型(Python 2.2之后将类和类型统一了,所以可以继承 Python 的内置数据类型)。当实例化 RoundFloat 的对象时,实际上是实例化了Python 内置数据类型 Float 的对象,并对这个对象做了一些定制化的操作(round(val, 2))。
NOTE:即便我们也可以通过重载 __init__()
来实现这个结果,但这里却不能这么做。因为如果 __new__()
没有被重载的话,仍会默认调用父类 Float 的构造器,创建 Float 类型的对象,而不是创建现在的 RoundFloat 类型对象。这也是两者的本质区别。
Python 进阶_OOP 面向对象编程_类属性和方法的更多相关文章
- Python 进阶_OOP 面向对象编程_实例属性和方法
目录 目录 构造器和解构器 构造器 __init__ 真构造器 __new__ 解构器 __del__ 实例方法 Python 中的 抽象方法 实例属性 查看实例属性 实例属性和类属性的区别 访问不可 ...
- Python 进阶_OOP 面向对象编程_类和继承
目录 目录 类 最简单的类 类方法 构造器 __init__ 创建一个类 实例化一个对象 调用实例的方法和属性 创建子类 使用 super 来调用父类的构造器 实例化子类对象 调用子类的属性和方法 类 ...
- Python 进阶_OOP 面向对象编程_组合与继承
#目录 前言 组合 派生 通过继承来覆盖重载方法 最常用的重载场景实例方法的重载 从标准类中派生类方法的重载 前言 我们定义一个类是希望能够把类当成模块来使用,并把类嵌入到我们的应用代码中,与其他的数 ...
- Python 进阶_OOP 面向对象编程_静态方法和类方法
目录 目录 静态方法 类方法 使用函数修饰符来声明静态方法和类方法 静态方法 静态方法仅是类中的函数, 不需要绑定实例, 也就是说静态方法的定义不需要传入 self 参数. 静态方法不属于类的某一个实 ...
- Python 进阶_OOP 面向对象编程_self 的实例绑定
目录 目录 self 和绑定 调用非绑定的方法 self 和绑定 在 Python 中 self 变量是特殊的, 其用于在实例方法中引用该方法所绑定的实例, 换句话说就是 Python 在实例化对象时 ...
- Python进阶之面向对象编程
面向对象编程——Object Oriented Programming,简称OOP,是一种程序设计思想.OOP把对象作为程序的基本单元,一个对象包含了数据和操作数据的函数. 面向过程的程序设计把计算机 ...
- Python进阶之面向对象编程(二)
Python面向对象编程(二) .note-content {font-family: "Helvetica Neue",Arial,"Hiragino Sans GB& ...
- Python进阶之面向对象编程概述
Python面向对象编程(一) .note-content {font-family: "Helvetica Neue",Arial,"Hiragino Sans GB& ...
- 第2课第1节_Java面向对象编程_类的引入_P【学习笔记】
摘要:韦东山android视频学习笔记 1. 面向对象编程的引入,我们先写一个简单的程序输出张三,李四的名字.代码如下,假如,现在我们要在名字前面添加籍贯广东,那样岂不是每个printf语句都得修改添 ...
随机推荐
- 5G网络的深度强化学习:联合波束成形,功率控制和干扰协调
摘要:第五代无线通信(5G)支持大幅增加流量和数据速率,并提高语音呼叫的可靠性.在5G无线网络中共同优化波束成形,功率控制和干扰协调以增强最终用户的通信性能是一项重大挑战.在本文中,我们制定波束形成, ...
- java_第一年_JDBC(4)
注:该篇只是为了小白的我熟悉下JDBC的代码,练习篇 在mysql中建test测试库,并创建一张employees表,加入一些数据如下图: 通过JDBC连接对表中数据进行添加: package lzj ...
- Java常见问题收集
转载处:https://blog.csdn.net/jackfrued/article/details/44921941 1.面向对象的特征有哪些方面? 答:面向对象的特征主要有以下几个方面: - 抽 ...
- Centos 7.6安装mysql服务端5.7
环境:centos 7.6,mysql server 5.7.26 新建文件夹/opt/mysql,并cd进去 运行wget http://dev.mysql.com/get/mysql-5.7.26 ...
- java crm 系统 进销存 springmvc SSM项目项目源码
统介绍: 1.系统采用主流的 SSM 框架 jsp JSTL bootstrap html5 (PC浏览器使用) 2.springmvc +spring4.3.7+ mybaits3.3 SSM 普 ...
- 20191108PHP数组查找练习
<?php $arr=[20,30,60]; $new=array(22,"tom"=>33); echo $arr[2]; echo $new['tom']; for ...
- javascript的继承模式
在javascript里面看到javascript的继承模式和传统的继承模式是有区别的,就想查资料看一下到底有区别,就看到了这篇文章,觉得讲得还可以,暂时先放上来,以后有别的东西再补充: http:/ ...
- 【LeetCode】抽样 sampling(共4题)
第一部分 水塘抽样 reservoir sampling 水塘抽样的原理:(应该开一篇新文章)pssss [382]Linked List Random Node (2018年11月15日,新算法) ...
- Sass函数:数字函数-ceil()函数
ceil() 函数将一个数转换成最接近于自己的整数,会将一个大于自身的任何小数转换成大于本身 1 的整数.也就是只做入,不做舍的计算: >> ceil(2.0) 2 >> ce ...
- 罗技K380使用手册
Ipad最佳伴侣|码字神器|罗技K380|附使用指南 ———— 为了方便平时在家处理工作➕写小红书笔记,年初买了个Ipad2018 我以前买过一个罗技的K480,因为太重了不方便携带,于是又入了K38 ...