Python面向对象-类成员

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

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

(一)字段

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

 1 class Province:
 2     # 静态字段
 3     country = "China"
 4
 5     def __init__(self, name):
 6         # 普通字段
 7         self.name = name
 8
 9 obj_henan = Province("HeNan")
10
11 print(obj_hunan.name) # 使用对象访问跑一趟那个字段
12 print(Province.country) # 使用类访问静态字段

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

由上图可是:

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

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

(二)方法

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

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

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

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

(三) 属性

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

假如我们有一个学生类:

1 class Student(object):
2     def __init__(self):
3         self.score = 0
4
5 s1 = Student()
6 s1.score = 9999

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

 1 class Student(object):
 2     def __init__(self):
 3         pass 4
 5     def set_score(self, value):
 6         if not isinstance(value, int):
 7             raise ValueError("Score must be int type")
 8         elif score < 0 or value> 100:
 9             raise ValueError("Score must between 0 - 100")
10         else:
11             self.score = value
12
13 s1 = Student()
14 s1.set_score(9999)

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

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

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

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

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

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

 1 class Student(object):
 2     def __init__(self):
 3         pass
 4
 5     @property
 6     def score(self, score):
 7         return self.score
 8
 9     @score.setter
10     def score(self, value): # 函数名和@property一致
11         if not isinstance(value, int):
12             raise ValueError("Score must be int type")
13         elif value < 0 or value > 100:
14             raise ValueError("Score must between 0 - 100")
15         else:
16             self.score = value
17
18 s1 = Student()
19 s1.score = 9999 # 这里用 "="访问score

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

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

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

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

 1     @property
 2     def birth(self):
 3         return self._birth
 4
 5     @birth.setter
 6     def birth(self, value):
 7         self._birth = value
 8
 9     @property
10     def age(self):
11         return 2017 - self._birth

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

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

时间: 2024-10-19 19:02:26

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

Python面向对象类成员特性

特性的存在就是将方法伪装成字段. property 把类方法当做普通字段去调用,即用对象调用的时候后面不用加括号 #!/usr/bin/env python # _*_coding:utf-8 _*_ class Foo:    @property    def Characteristic(self):        print("类方法的特性") # 创建一个对象 obj = Foo() # 调用类方法的时候方法后面不用加括号 obj.Characteristic 输出 /usr/

面向对象类成员

面向对象类成员:字段,方法,属性 一.字段: 举个例子: class Foo: def __init__(self, name): self.name = name 其中的self.name就是字段,不过这是一个普通的字段,保存在对象中,可以通过对象去访问例如: 1 obj = Foo("DJC") 2 print(self.name) 3 4 >>>DJC 除了普通字段还有静态字段来看以下代码: class Foo: s = 123 def __init__(sel

python面向对象之类成员

一.概述 上篇<python面向对象OOP>介绍了python面向对象的基础初级入门部分,提到了类的定义,使用,类的三大特性;经典类,新式类在查找时的区别等,有了前面的基础,本文接着描述面向对象中类成员;先整体描述下,类中的成员分以下几部分: #类成员  #字段(属性):      普通字段  属于对象,保存在对象中,只能通过对象访问      静态字段  属于类,保存(一份)在类中(所有对象共享的字段属性),执行时可以是类访问也可以是对象访问  #方法:      普通方法  保存在类中,又

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

每个类成员函数都只涉及一个对象, 即调用它的对象. 但有时候方法可能涉及到两个对象, 在这种情况下需要使用C++ 的 this 指针 假设将方法命名为topval(), 则函数调用stock1.topval()将访问stock1的对象数据:stock2.topval()将访问stock2的对象数据: 如果希望该方法的两个对象进行对比, 则必须将第二个对象作为参数传递给它.这时候涉及到隐式和显式: top = stock1.topval(stock2); 隐式的访问了stock1, 显示的访问了s

Python的类成员变量默认初始值的坑

问题发现:一个循环内,缺省值初始化同名变量,其中的list成员不是空,会延续之前同名变量的值. 示例代码: # Define class class Variant(): # use def __init__(self, price = 500, description = 'default description', values = ['', '', '']): self.price = price self.description = description self.values = v

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

#类成员: #字段 self.xy =qq . xy=qq #普通字段 (保存在对象里面) #直接通过点(.)+ 字段 进行调用 #静态字段 (保存在类里面) #静态字段属于类,在内存只保留一份 . 把公共的字段 放到类中 ,节省内存等好处 #代码从上到下解释到类就创建了 #可以通过 类.静态字段 进行访问 #方法 def xx() # (保存在类里面) #通过点(.) + 方法名 + 括号 进行调研 #通过 类 点(.) 方法名也可以调用 . 还是要在前面先实例化一个对象 #静态字段class

python面向对象--类与对象

一.类与对象概念 1.面向对象的两个重要概念 1)类:共性事物的抽象,是对某一类具有共性事物的描述,是概念上的定义. 2)对象:是共性事物的一个体现,是这类事物的每个个体,或者说是类的一个实例 总结:类是对象的模板,对象是类的实例 2.类结构:里面包含属性和函数 3.数据是对象的状态-->成员变量(属性) 方法是对象的行为-->函数(方法) 二.类的语法 class Math: a = 4 #属性 b = 5 def add(self): #方法 c = self.a + self.b ret

面向对象-类-成员变量-局部变量-this

1.能够理解面向对象的思想     面向对象是基于面向过程的编程思想,强调的是对象,由对象去调用功能.它是一种更符合人类习惯的编程思想,可以将复杂的事情简单化,将我们的角色从执行者变成了指挥者. 2.能够明确类与对象关系     类是客观世界中相关事物的基本特征抽象.对象是该类事物的具体体现.比如手机是一个类,而iphone7就是一个对象. 3.定义学生类 public class Student{     //成员变量     String name;     int age; //成员方法 

python面向对象类

面向对象变成介绍 面向过程编程 核心是过程(流水线式思维),过程即解决问题的步骤,面向过程的设计就好比精心设计好一条流水线,考虑周全什么时候处理什么东西.主要应用在一旦完成很少修改的地方,如linux内核.git.apache服务器等 优点:极大的降低了程序的设计复杂度 缺点:可扩展性差,改动一个地方很可能要改多个地方,牵一发而动全身 面向对象编程:不是编程的全部,只是用来解决软件可扩展性的 核心是对象(上帝式思维),对象作为程序的基本单元,一个对象包含了数据和操作数据的函数.面向对象就是把计算