Python中类(Class)使用

在Python中所有数据类型都可以被视为对象,而类(Class)是用来描述具有相同的属性和方法的对象的集合,所有它定义了每个集合中对象所共有的属性和方法。

一、Python类的定义与实例的创建

在Python学习中,类(Class)是面向对象最重要的概念之一。通过对类(Class)知识的学习能使初学者对面向对象编程(object)有更深一步的理解。

1 问题

写一个Student类,该类有学生的姓名和成绩,该类有一个方法可以打印该学生的姓名,成绩,和等级。

大于等于90为A,89到60为B,小于60为C

2 方法

用文字描述解题思路,可配合一些图形进行描述以便更好的阐述。

1、定义类使用class关键字,class后面紧接类名,类名通常以大写开头的单词(无类继承时类名后括号可以选择不添加)。

class Student(object):#完成对类的定义

2、进入类定义时,就会创建一个新的命名空间,并把它用作局部作用域,因此函数定义会绑定到这个局部作用域中。通过定义一个特殊的__init__方法,在创建实例的时候,就把name,score等属性绑定。

3、通过定义函数,使用if语句完成对不同分值的等级判定,将学生成绩等级进行绑定完成。

3 实验结果与讨论

通过实验、实践等证明提出的方法是有效的,是能够解决开头提出的问题。

代码清单 1

在Python中,类通过 class 关键字定义,类名通用习惯为首字母大写,Python3中类基本都会继承于object类,语法格式如下,我们创建一个Circle圆类:

注意:我们定义的类都会继承于object类,当然也可以不继承object类;两者区别不大,但没有继承于object类使用多继承时可能会出现问题。

有了Circle类的定义,就可以创建出具体的circle1、circle2等实例,circle1和circle2是个实际的圆。创建实例使用 类名+(),类似函数调用的形式创建。

class Circle(object):  # 创建Circle类,Circle为类名
   pass  # 此处可添加属性和方法

circle1= Circle()
circle2= Circle()

代码清单 2

Class student (object) :
def __init__ (self, name, score) :
    self. Name=name
    self. Score=score
    def getgrande(self) :
        if self.score>=90:
        return ‘A’
        elif 60<=self. score<9o:
        return ‘B’
        else:
        return ‘C’
daming=Student(‘lisa’,85)
print(‘%s,%s’%(daming.name,daming.score))

二、Python类中的实例属性与类属性

类的属性是用来表明这个类是什么的。

类的属性分为实例属性类属性两种。

实例属性用于区分不同的实例;
类属性是每个实例的共有属性。

区别:实例属性每个实例都各自拥有,相互独立;而类属性有且只有一份,是共有的属性。

1、实例属性

类的属性都是用来指明这个类”是什么”,实例属性是用来区分每个实例不同的基础。

在上面我们创建了Circle类,大家都知道所有圆都具备半径这个通用属性,下面我们为circle1、circle2 圆实例添加半径 r 这个属性并赋值。

circle1.r=1# r为实例属性
circle2.R=2print(circle1.r)# 使用 实例名.属性名 可以访问我们的属性
print(circle2.R)

如上 circle1.r、circle2.R 大小写有区分,两个实例的属性名称不统一不利于后面的访问和使用,而且每次在创建圆后我们要再为实例添加属性会比较麻烦,所以我们可以在创建实例时给类初始属性。

在定义 Circle 类时,可以为 Circle 类添加一个特殊的 __init__() 方法,当创建实例时,__init__() 方法被自动调用为创建的实例增加实例属性。

我们在此为每个实例都统一加上我们需要的属性(用法类似java的构造方法):

classCircle(object):# 创建Circle类
def__init__(self,r):# 初始化一个属性r(不要忘记self参数,他是类下面所有方法必须的参数)
self.r=r# 表示给我们将要创建的实例赋予属性r赋值

注意:__init__() 方法的第一个参数必须是 self(self代表类的实例,可以用别的名字,但建议使用约定成俗的self),后续参数则可以自由指定,和定义函数没有任何区别。

拓展:__init__() 方法的用法类似java中的构造方法,但它不是构造方法,Python中创建实例的方法是__new__() ,这个方法在python大多数使用默认方法,不需要重新定义,初学者不用关注__new()__方法。

相应,创建实例时就必须要提供除 self 以外的参数:

circle1=Circle(1)# 创建实例时直接给定实例属性,self不算在内
circle2=Circle(2)
print(circle1.r)# 实例名.属性名 访问属性print(circle2.r)# 我们调用实例属性的名称就统一了

注意:实例名.属性名 circle1.r 访问属性,是我们上面Circle类__init__() 方法中 self.r 的 r 这个实例属性名,而不是__init__(self, r)方法中的 r 参数名,如下更加容易理解:

classCircle(object):# 创建Circle类
def__init__(self,R):# 约定成俗这里应该使用r,它与self.r中的r同名
self.r=Rcircle1=Circle(1)
print(circle1.r)#我们访问的是小写r
面试喜欢问的问题:创建类时,类方法中的self是什么?
self 代表类的实例,是通过类创建的实例 (注意,在定义类时这个实例我们还没有创建,它表示的我们使用类时创建的那个实例)

2、类属性

绑定在实例上的属性不会影响其他实例,但类本身也是一个对象,如果在类上绑定属性,则所有实例都可以访问该类的属性,并且所有实例访问的类属性都是同一个!!!记住,实例属性每个实例各自拥有,互相独立,而类属性有且只有一份。

圆周率π为圆的共有属性,我们可以在Circle类添加pi这个类属性,如下:

classCircle(object):
pi=3.14# 类属性
def__init__(self,r):
self.r=rcircle1=Circle(1)
circle2=Circle(2)
print('----未修改前-----')
print('pi=\t',Circle.pi)
print('circle1.pi=\t',circle1.pi)#  3.14
print('circle2.pi=\t',circle2.pi)#  3.14
print('----通过类名修改后-----')Circle.pi=3.14159# 通过类名修改类属性,所有实例的类属性被改变
print('pi=\t',Circle.pi)#  3.14159
print('circle1.pi=\t',circle1.pi)#  3.14159
print('circle2.pi=\t',circle2.pi)#  3.14159
print('----通过circle1实例名修改后-----')circle1.pi=3.14111# 实际上这里是给circle1创建了一个与类属性同名的实例属性
print('pi=\t',Circle.pi)#  3.14159
print('circle1.pi=\t',circle1.pi)# 实例属性的访问优先级比类属性高,所以是3.14111   
print('circle2.pi=\t',circle2.pi)#  3.14159
print('----删除circle1实例属性pi-----')

输出结果:

----未修改前-----
pi=3.14
circle1.pi=3.14
circle2.pi=3.14
----通过类名修改后-----
pi=3.14159
circle1.pi=3.14159
circle2.pi=3.14159
----通过circle1实例名修改后-----
pi=3.14159
circle1.pi=3.14111
circle2.pi=3.14159

仔细观察我们通过类创建的实例修改的类属性后,通过其他实例访问类属性他的值还是没有改变。其实是通过实例修改类属性是给实例创建了一个与类属性同名的实例属性而已,实例属性访问优先级比类属性高,所以我们访问时优先访问实例属性,它将屏蔽掉对类属性的访问。

我们删除circle1实例的实例属性pi,就能访问该类的类属性了。

print('----删除circle1实例属性pi-----')
delcircle1.piprint('pi=\t',Circle.pi)
print('circle1.pi=\t',circle1.pi)
print('circle2.pi=\t',circle2.pi)

输出结果:

----删除circle1实例属性pi-----
pi=  3.14159
circle1.pi=  3.14159
circle2.pi=  3.14159

可见,千万不要在实例上修改类属性,它实际上并没有修改类属性,而是给实例绑定了一个实例属性。

三、Python类的实例方法

方法是表明这个类用是来做什么。

在类的内部,使用 def 关键字来定义方法,与一般函数定义不同,类方法必须第一个参数为 self, self 代表的是类的实例(即你还未创建类的实例),其他参数和普通函数是完全一样。

如下我们给圆类 Circle 添加求面积的方法 get_area :

classCircle(object):
pi=3.14# 类属性
def__init__(self,r):self.r=r# 实例属性
defget_area(self):""" 圆的面积 """# 
return self.r**2 * Circle.pi # 通过实例修改pi的值对面积无影响,这个pi为类属性的值
returnself.r**2*self.pi# 通过实例修改pi的值对面积我们圆的面积就会改变
circle1=Circle(1)print(circle1.get_area())# 调用方法 self不需要传入参数,不要忘记方法后的括号  输出 3.14

注意:示例中的 get_area(self) 就是一个方法,它的第一个参数是 self 。__init__(self, name)其实也可看做是一个特殊的实例方法。

在方法的内部需要调用实例属性采用 “self.属性名 ” 调用。示例中 get_area(self) 对于 pi 属性的引用 Circle.pi 与 self.pi 存在一定区别。

Circle.pi 使用的是类属性 pi,我们通过创建的实例去修改 pi 的值对它无影响。self.pi 为实例的 pi 值,我们通过创建的实例去修改 pi 的值时,由于使用 self.pi 调用的是实例属性,所以 self.pi 是修改后的值。

调用实例的方法中使用实例属性可采用 实例名.方法名(除self的参数) 使用。

四、总结

参数的传递图,翻译与pythoncentral网

In 1 and 2, the arguments are passed to the method.

1和2参数传递给__init__方法中的data参数

On 3, the self argument refers to the instance.

3self 参数指向当前实例自身,self代表创建的实例变量 ik1 或者 Kls(‘arun’)。

At 4, we do not need to provide the instance to the method, as it is handled by the interpretor itself.

4 我们不需要传递实例自身给方法,Python解释器自己会做这些操作的;ik14 会自动作为第一个实例参数(self)传入方法中。

文章出处登录后可见!

已经登录?立即刷新

共计人评分,平均

到目前为止还没有投票!成为第一位评论此文章。

(0)
心中带点小风骚的头像心中带点小风骚普通用户
上一篇 2023年12月23日
下一篇 2023年12月23日

相关推荐