类的成员可以分为三大类:字段、方法和属性:

注:所有成员中,只有普通字段的内容保存对象中,即:根据此类创建了多少对象,在内存中就有多少个普通字段。而其他的成员,则都是保存在类中,即:无论对象的多少,在内存中只创建一份。

(一)字段

字段包括:普通字段和静态字段,他们在定义和使用中有所区别,而最本质的区别是内存中保存的位置不同

 class Province:
# 静态字段
country = "China" def __init__(self, name):
# 普通字段
self.name = name obj_henan = Province("HeNan") print(obj_hunan.name) # 使用对象访问跑一趟那个字段
print(Province.country) # 使用类访问静态字段

由上述代码可以看出【普通字段需要通过对象来访问】【静态字段通过类访问】,在使用上可以看出普通字段和静态字段的归属是不同的。其在内容的存储方式类似如下图:

由上图可是:

  • 静态字段在内存中只保存一份
  • 普通字段在每个对象中都要保存一份

应用场景: 通过类创建对象时,如果每个对象都具有相同的字段,那么就使用静态字段

(二)方法

方法包括:普通方法、静态方法和类方法,三种方法在内存中都归属于类,区别在于调用方式不同。

  • 普通方法:由对象调用;至少一个self参数;执行普通方法时,自动将调用该方法的对象赋值给self
  • 类方法:由调用; 至少一个cls参数;执行类方法时,自动将调用该方法的复制给cls
  • 静态方法:由调用;无默认参数;
 class Foo:
def __init__(self, name):
self.name = name # 普通方法,由对象调用
def ord_fun(self):
print(self.name) # 静态方法
# 普通方法经过两步变成静态字段,1,去掉参数self,2,加上装饰器 @staticmethod
# 如果类里的方法用不到对象(self)里的字段,静态方法可以有除了self的参数
# 静态方法其实就是面向过程里的普通函数,之所以放到类里就是表示方法和该类有关
@staticmethod
def static_func(arg1):
print(arg1) # 类方法
# 静态方法的一种特殊形式,自带特殊参数cls,使用装饰器 @classmethod
@classmethod
def class_func(cls): # cls = class
print(cls) obj_foo = Foo("foo object")
obj_foo.ord_fun()
Foo.static_func("static func")
Foo.class_func()

相同点:对于所有的方法而言,均属于类(非对象)中,所以,在内存中也只保存一份。

不同点:方法调用者不同、调用方法时自动传入的参数不同。

(三) 属性

为了理解Python的属性,我们先来看一个例子,

假如我们有一个学生类:

 class Student(object):
def __init__(self):
self.score = 0 s1 = Student()
s1.score = 9999

这个赋值 s1.score = 9999 这显然不合逻辑,score的正常取值范围应该是0-100, 为了限制score的范围,我们可能会通过定义一个set_score()方法来设置成绩,再通过一个get_score()来获取成绩,这样,在set_score()方法里,就可以检查参数:

 class Student(object):
def __init__(self):
pass
def set_score(self, value):
if not isinstance(value, int):
raise ValueError("Score must be int type")
elif score < 0 or value> 100:
raise ValueError("Score must between 0 - 100")
else:
self.score = value s1 = Student()
s1.set_score(9999)

这时 s1.set_score(9999) 就会有如下的报错:

     raise ValueError("Score must between 0 - 100")
ValueError: Score must between 0 - 100

但是,上面的调用方法又略显复杂

有没有既能检查参数,又可以类似于访问字段一样设置score的方法呢?(使用score = 9999,而不用s1.set_score(9999)), 对于追求完美的Python程序员来说,这是必须要做到的!

还记得装饰器(decorator)可以给函数动态加上功能吗?对于类的方法,装饰器一样起作用。Python内置的@property装饰器就是负责把一个方法变成属性调用的:

于是我们对上面的Studeng类做修改:

 class Student(object):
def __init__(self):
pass @property
def score(self, score):
return self.score @score.setter
def score(self, value): # 函数名和@property一致
if not isinstance(value, int):
raise ValueError("Score must be int type")
elif value < 0 or value > 100:
raise ValueError("Score must between 0 - 100")
else:
self.score = value s1 = Student()
s1.score = 9999 # 这里用 "="访问score

@property的实现比较复杂,我们先考察如何使用。把一个getter方法变成属性,只需要加上@property就可以了,此时,@property本身又创建了另一个装饰器@score.setter,负责把一个setter方法变成属性赋值,于是,我们就拥有一个可控的属性操作:

 raise ValueError("Score must between 0 - 100")
ValueError: Score must between 0 - 100

注意到这个神奇的@property,我们在对实例属性操作的时候,就知道该属性很可能不是直接暴露的,而是通过getter和setter方法来实现的。

还可以定义只读属性,只定义getter方法,不定义setter方法就是一个只读属性:

     @property
def birth(self):
return self._birth @birth.setter
def birth(self, value):
self._birth = value @property
def age(self):
return 2017 - self._birth

上面的birth是可读写属性,而age就是一个只读属性,因为age可以根据birth和当前时间计算出来。

@property广泛应用在类的定义中,可以让调用者写出简短的代码,同时保证对参数进行必要的检查,这样,程序运行时就减少了出错的可能性。

Python面向对象-类成员的更多相关文章

  1. python 面向对象类成员(字段 方法 属性)

    一.字段 字段包括:普通字段和静态字段,他们在定义和使用中有所区别,而最本质的区别是内存中保存的位置不同, 普通字段属于对象 静态字段属于类 class Province: # 静态字段 countr ...

  2. python 面向对象(类的特殊成员)

    python 面向对象: (思维导图 ↑↑↑↑) 类的特殊成员 python的类成员存在着一些具有特殊含义的成员 1.__init__: 类名() 自动执行 __init__ class Foo(ob ...

  3. python面向对象(类的成员及类方法)

    类的普通成员 字段 方法 属性 类的高级成员 静态字段 静态方法 属性方法   类方法 类成员修饰符 类的成员 类的成员可以分为三大类:字段.方法和属性 注:所有成员中,只有普通字段的内容保存对象中, ...

  4. python 面向对象(类)

    面向对象,即是将具备某种共性的事物抽象成一个类(模板),然后再根据类来创建实例对象进行具体的使用. 概述 面向过程:根据业务逻辑从上到下写垒代码 函数式:将某功能代码封装到函数中,日后便无需重复编写, ...

  5. Python面向对象之成员修饰符

    对于这些类成员有修饰符 之前定义字段country任何对象都可以访问,是公有的 可以定义为私用属性,只有类内部的方法可以调用,外部不能直接调用,但是可以间接调用 vim day7-10.py #!/u ...

  6. C++ 面向对象 类成员函数this指针

    每个类成员函数都只涉及一个对象, 即调用它的对象. 但有时候方法可能涉及到两个对象, 在这种情况下需要使用C++ 的 this 指针 假设将方法命名为topval(), 则函数调用stock1.top ...

  7. python面向对象(类和对象及三大特性)

    类和对象是什么 创建类 新式类 和 经典类 面向对象三大特性 继承 封装 多态   面向对象是一种编程方式,此编程方式的实现是基于对 类 和 对象 的使用 类 是一个模板,模板中包装了多个“函数”供使 ...

  8. Python面向对象(特殊成员)

    day25 __init__     类()自动执行     __del__     __call__     对象()  类()() 自动执行     __int__      int(对象)    ...

  9. python面向对象的成员、属性等

    #类成员: #字段 self.xy =qq . xy=qq #普通字段 (保存在对象里面) #直接通过点(.)+ 字段 进行调用 #静态字段 (保存在类里面) #静态字段属于类,在内存只保留一份 . ...

随机推荐

  1. 大专生自学iOS到找到工作的前前后后

    先做个自我介绍,我13年考上一所很烂专科民办的学校,学的是生物专业,具体的学校名称我就不说出来献丑了.13年我就辍学了,我在那样的学校,一年学费要1万多,但是根本没有人学习,我实在看不到希望,我就退学 ...

  2. 【js】中的小技巧

    本文主要介绍一些JS中用到的小技巧 1. 类型强制转换   1.1 string强制转换为数字 可以用*1来转化为数字(实际上是调用.valueOf方法) 然后使用Number.isNaN来判断是否为 ...

  3. 爬虫——Scrapy框架案例二:阳光问政平台

    阳光热线问政平台 URL地址:http://wz.sun0769.com/index.php/question/questionType?type=4&page= 爬取字段:帖子的编号.投诉类 ...

  4. PHP的发展历程

    PHP的发展历程 了解一门语言,我们必须知道这门语言的发展史,现在我通过版本的变化以时间轴的形式来说明PHP的发展历程. 1.1995年初PHP1.0诞生 Rasmus Lerdof发明了PHP,这是 ...

  5. 大数据学习--day05(嵌套循环、方法、递归)

    嵌套循环.方法.递归 图形打印 public static void main(String[]arg) { /** * * * * * * */ // 3 2 1 0 // 1 3 5 for(in ...

  6. python3 安装pyhanlp方法

    直接pip install pyhanlp的时候会提示缺少Microsoft Visual c++环境, 其实没有Microsoft Visual c++环境也是可以的, 可以先安装jpype1,然后 ...

  7. 通过samba服务将centos7指定文件挂载到window下

    做嵌入式开发,windows下编辑代码,虚拟机上编译,为了方便打算在虚拟机下搭一个samba服务器,将文件夹映射到windows下,搜索网上的方法,内容大同小异,试了半天终于成功了.特此记录一下步骤, ...

  8. ruby 批量下载王者荣耀皮肤

    主要采用ruby Parallel库提供的多线程方式: require 'unirest' require 'open-uri' require 'parallel' require 'json' u ...

  9. STM32 时钟配置的坑

    今天在调试公司的一款产品的时候发现8M的晶振用完了,于是找了一个16M的替代 坑爹的就在这里,明明已经把时钟按照时钟树配置好了,但是串口等外设一直无法正常工作 折腾了一下午,终于发现这位老兄的文章ht ...

  10. [HDU6326]Monster Hunter(贪心)

    用(a,b)表示一个点先失去a点HP,然后增加b点HP 首先容易证明忽略父亲条件下,任意两个点,先吃b大的最优 对于一个节点v和它的父节点u,若此时选v最优,那么就是吃到u时可以立即吃掉v, 于是可以 ...