python基础类的定义与使用
Posted 非晚非晚
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了python基础类的定义与使用相关的知识,希望对你有一定的参考价值。
文章目录
1. 类的定义和使用
- 类(Class): 用来描述具有相同的
属性和方法的对象的集合
。它定义了该集合中每个对象所共有的属性和方法。对象是类的实例。- 类变量(类属性):类变量在整个实例化的对象中是
公用的
。类变量定义在类中且在函数体之外
。类变量通常不作为实例变量使用。- 数据成员:类变量或者实例变量用于处理类及其实例对象的相关的数据。
- 实例变量(实例属性):定义在
方法中的变量
,只作用于当前实例的类。- 方法:类中定义的函数。
- 方法重写:如果从父类继承的方法不能满足子类的需求,可以对其进行改写,这个过程叫方法的覆盖(override),也称为方法的重写。
- 继承:即一个派生类(derived class)继承基类(base class)的字段和方法。继承也允许把一个派生类的对象作为一个基类对象对待。例如,有这样一个设计:一个Dog类型的对象派生自Animal类,素以Dog也是一个Animal。
- 实例化:创建一个类的实例,
类的具体对象
。- 对象:通过类定义的数据结构实例。对象包括两个
数据成员
(类变量和实例变量)和方法
。
类就是一个模板,模板里可以包含多个函数,函数里实现一些功能。对象则是根据模板创建的实例,通过实例对象可以执行类中的函数。
一个典型的类的定义和使用例子如下:
#创建类
class Foo: #class是关键字,Foo是类名
class_int = 10 #类变量
#创建类中的函数(方法)
def bar(self,name): #self是特殊参数,类的实例化,必须填写。
print('bar')
obj = Foo() #根据Foo创建对象obj
print('类访问类变量:',Foo.class_int)
print('对象访问类变量:', obj.class_int)
obj.bar(3)
输出:
类访问类变量: 10
对象访问类变量: 10
bar
类的使用请注意:
- 调用类属性:
⑴类中访问类变量:类名. 类变量名
⑵类外访问类变量:类名.类变量名或实例名.类变量名
- 调用实例属性:
⑴类中访问实例变量:self.实例变量名
⑵类外访问实例变量:实例名.实例变量名
- 调用实例方法:
⑴类中访问实例方法:self.方法名(参数)或类名.方法名(self,参数)
⑵类外访问实例方法:实例名.方法名(参数)
2. 对象的三大特性
和所有的面向对象语言一样,python对象也有三大特性,它们分别为封装、继承和多态
。
2.1 封装
封装,顾名思义就是将内容封装到某个地方,以后再去调用被封装在某处的内容。
(1)通过对象调用被封装的内容
通过:对象.属性名
的方式访问实例化对象。具体访问形式如下:
class Foo:
def __init__(self, name, age):
self.name = name
self.age = age
obj = Foo('xiaoming', 22)
print(obj.name,obj.age)
print(type(obj))
输出:
xiaoming 22
<class '__main__.Foo'>
(2)通过self间接访问被封装的内容
其实self就是实例化对象本身,所以可以通过它对实例化对象进行访问。
class Foo:
def info(self):
print(self.name,self.age)
def __init__(self, name, age):
self.name = name
self.age = age
obj = Foo('xiaoming', 22)
obj.info()
输出:
xiaoming 22
2.2 继承
和现实中一样,子类可以继承父类中的内容。比如,首先创建一个Animal类,然后cat和dog分别继承它。
class Animal:
def eat(self):
print("%s 吃 " % self.name)
def drink(self):
print("%s 喝 " % self.name)
def shit(self):
print("%s 拉 " % self.name)
def pee(self):
print("%s 撒 " % self.name)
class Cat(Animal):
def __init__(self, name):
self.name = name
self.breed = '猫'
def cry(self):
print('喵喵叫')
class Dog(Animal):
def __init__(self, name):
self.name = name
self.breed = '狗'
def cry(self):
print('汪汪叫')
# ######### 执行 #########
c1 = Cat('小明家的小猫')
c1.eat()
d1 = Dog('小红家的小狗')
d1.eat()
小明家的小猫 吃
小红家的小狗 吃
2.3 多态
python中的多态,不像C++中父类与子类中的多态一样。它需要根据对象的具体指向来决定方法的指向。具体示例如下,S1和S2都实现了show方法,具体看它的指向来决定调用哪一个。
class F1:
pass
class S1(F1):
def show(self):
print('S1.show')
class S2(F1):
def show(self):
print('S2.show')
def Func(obj):
obj.show()
s1_obj = S1()
Func(s1_obj)
s2_obj = S2()
Func(s2_obj)
输出:
S1.show
S2.show
3. 属性(变量)绑定
Python作为动态语言,类对象和实例对象都可以在运行时绑定任意属性。因此,类属性的绑定发生在两个地方,类定义时和运行的任意阶段
。
3.1 类属性绑定
下面程序中介绍了类中和类外的类属性绑定方法,同时类属性也可以被删除
。
class Dog:
kind = 'canine' #类中,类属性绑定
Dog.country = 'China' # 类外,类属性绑定
print(Dog.kind, ' - ', Dog.country) # 输出: canine - China
del Dog.kind #删除类属性
print(Dog.kind, ' - ', Dog.country) # 类属性被删除,报错!
输出:
canine - China
Traceback (most recent call last):
File "/home/liqiang/workspace/python/python_tutorials/main.py", line 8, in <module>
print(Dog.kind, ' - ', Dog.country) # 类属性被删除,报错!
AttributeError: type object 'Dog' has no attribute 'kind'
3.2 实例属性绑定
与类属性绑定相同,实例属性绑定也发生在两个地方:类定义时、运行时任意阶段。
class Dog:
def __init__(self, name, age):
self.name = name #类中,实例绑定
self.age = age
dog = Dog('Lily', 3)
dog.fur_color = 'red' # 类外,实例属性绑定
print('%s is %s years old, it has %s fur' % (dog.name, dog.age, dog.fur_color))
输出:
Lily is 3 years old, it has red fur
4. 属性引用
4.1 类属性引用
类属性分为两种:数据属性、方法属性。只是通常很少有引用类函数属性的需求。
数据属性
class Dog:
kind = 'canine'
Dog.country = 'China'
print(Dog.kind, ' - ', Dog.country) #这两个都是类数据属性的引用
输出:
canine - China
4.2 实例属性引用
实例对象可以引用类属性和实例属性
,遵循的规则如下:
先查找实例属性,后查找类属性
。- 属性绑定时,总是为实例对象创建新属性(
即使存在相同的类属性
),属性存在时,只更新属性执行的对象
。
代码示例1:
class Dog:
kind = 'canine'
country = 'China'
def __init__(self, name, age, country):
self.name = name
self.age = age
self.country = country
dog = Dog('Lily', 3, 'Britain')
print(dog.name, dog.age, dog.kind, dog.country)
输出:
Lily 3 canine Britain
说明:类对象Dog与实例对象dog均有属性country,按照规则,dog.country会引用到实例对象的属性;但实例对象dog没有属性kind,按照规则会引用类对象的属性。
代码实例2:
class Dog:
kind = 'canine'
country = 'China'
def __init__(self, name, age, country):
self.name = name
self.age = age
self.country = country
dog = Dog('Lily', 3, 'Britain')
print(dog.name, dog.age, dog.kind, dog.country)
print(dog.__dict__)
dog.kind = 'feline' #新增实例属性,不会改变类属性的值
print(dog.name, dog.age, dog.kind, dog.country)
print(dog.__dict__)
print(Dog.kind) #类属性并没有改变
输出:
Lily 3 canine Britain
'name': 'Lily', 'age': 3, 'country': 'Britain'
Lily 3 feline Britain
'name': 'Lily', 'age': 3, 'country': 'Britain', 'kind': 'feline'
canine
说明:类外使用新增实例属性,并不会影响类属性
。
4.3 可变类属性引用
下列代码中 self.tricks.append(trick)
为可变类属性引用,而不是实例属性!
class Dog:
tricks = []
def __init__(self, name):
self.name = name
def add_trick(self, trick):
self.tricks.append(trick) #这里是可变的类属性引用,而不是实例子属性
d = Dog('Fido')
e = Dog('Buddy')
d.add_trick('roll over')
e.add_trick('play dead')
print(d.tricks)
输出:
['roll over', 'play dead']
如果想要使用实例属性,可以在先定义self.tricks,然后再append。如下:
class Dog:
tricks = []
def __init__(self, name):
self.name = name
def add_trick(self, trick):
self.tricks = []
self.tricks.append(trick) #这里是可变的类属性引用,而不是实例子属性
d = Dog('Fido')
e = Dog('Buddy')
d.add_trick('roll over')
e.add_trick('play dead')
print(d.tricks)
print(e.tricks)
输出:
['roll over']
['play dead']
4.4 一个例子说明类属性、实例属性与普通变量
class TestClass(object):
val1 = 100
def __init__(self):
self.val2 = 200
def fcn(self, val=400):
val3 = 300
self.val4 = val
self.val5 = 500
if __name__ == '__main__':
inst = TestClass()
print(TestClass.val1)
print(inst.val1)
print(inst.val2)
#print(inst.val3) # val3为局部变量,报错!!!
#print(inst.val4) # val4不是实例属性,报错!!!
#print(inst.val5)# val5不是实例属性,报错!!!
print(inst.__dict__)
输出:
100
100
200
'val2': 200
可以看出inst只有一个实例属性,也就是val2
。
- val1是类变量,可以由类名直接调用,也可以有对象来调用;
- val2是实例变量,可以由类的对象来调用,这里可以看出成员变量一定是以self.的形式给出的,因为self的含义就是代表实例对象
- val3既不是类变量也不是实例变量,它只是函数fcn内部的局部变量
val4和val5也都不是实例变量,虽是以self.给出,但并没有在构造函数中初始化
5. 方法
5.1 实例方法、类方法和静态方法
- 实例方法:一般在类中定义的方法,默认都为实例方法。实例方法最大的特点就是最少要包含一个self参数,该参数必须定义,但调用时不需要传。类比C++中的this指针。
- 类方法:类方法至少需要包含一个参数(cls),但在调用类方法时,无需显式为cls参数传递参数。
类方法需要使用修饰语句: @classmethod
。类和实例对象都可以调用类方法
。- 静态方法:
与普通函数类似
,只是它在类命名空间中定义,而函数实在程序的全局命名空间中定义。它有以下特点:
- 类静态方法
没有self、cls这样的特殊参数
;- 类静态方法中
无法调用任何类和对象的属性和方法
,类静态方法与类的关系不大;- 静态方法需要使用
@staticmethod修饰
;- 可以使用
类或实例对象调用
它。
- 类方法举例
class CLanguage:
def __init__(self):
self.name = "小明"
self.age = "22"
# 下面定义了一个类方法
@classmethod
def info(cls):
print("正在调用类方法", cls)
# 使用类名直接调用类方法
CLanguage.info()
# 使用类对象调用类方法
clang = CLanguage()
clang.info()
输出:
正在调用类方法 <class '__main__.CLanguage'>
正在调用类方法 <class '__main__.CLanguage'>
- 静态方法举例
class CLanguage:
@staticmethod
def info(name, age):
print(name, age)
# 使用类名直接调用静态方法
CLanguage.info("xiaoming", "22")
# 使用类对象调用静态方法
clang = CLanguage()
clang.info("xiaohong", "23")
输出:
xiaoming 22
xiaohong 23
5.2 实例方法中调用其它方法
内部调用实例方法需要加slef
。
class Dog():
def __init__(self, name, age):
self.name = name
self.age = age
def get_dog_information(self):
dog_information = "name is 0,age is 1".format(self.name, self.age)
return dog_information
def get_dog_speak(self, love):
dog_speak = self.get_dog_information() + love #内部调用实例方法
return dog_speak
dog = Dog("jake", 13)
print(dog.get_dog_speak("swimming"))
输出:
name is jake,age is 13swimming
以上是关于python基础类的定义与使用的主要内容,如果未能解决你的问题,请参考以下文章