一、类与对象的成员
1.1 类的成员
1.1.1 类的成员定义
成员是指对象特有的一些属性,如人的身高、性别、年龄、学历等等。属于类的成员是该类所有对象共享的,类成员属于类,可以通过类名或对象名访问。下面我们以一个Student类来解释一下:
class Student(object):
age = 20
student1 = Student()
student2 = Student()
print(Student.age)
print(student1.age)
print(student2.age)
20
20
20
我们先定义了一个Student类,然后定义了一个类成员age,然后我们可以通过类名访问,也可以通过对象名访问。
1.1.2 修改和增加类成员
Python支持修改和动态增加类成员,我们看下面的例子:
class Student(object):
age = 20
Student.age = 22
Student.height = 180
student1 = Student()
student2 = Student()
print(Student.age)
print(student1.age)
print(student2.age)
print(Student.height)
print(student1.height)
print(student2.height)
22
22
22
180
180
180
我们可以发现类成员的值修改了,而且增加了一个类成员
1.2 对象的成员
1.2.1 对象的成员的定义
属于对象的成员主要指在构造函数__init__()中定义的,定义和使用时必须以 self 作为前缀,self 相当于对象本身,传入参数时不需要传入self参数。同一个类的不同对象之间的成员互不影响,只能通过对象名访问,下面以Student类来创建实例:
class Student(object):
def __init__(self,age,height):
self.age = age
self.height = height
student1 = Student(age = 20, height = 175)
student2 = Student(age = 25, height = 185)
print(student1.age)
print(student2.age)
print(student1.height)
print(student2.height)
20
25
175
185
由此可见,我们由Student类实例化的两个对象是不一样的。
1.2.2 修改和增加对象的成员
1、修改对象的成员,例子如下:
class Student(object):
def __init__(self,age):
self.age = age
student1 = Student(age = 20)
student2 = Student(age = 25)
print(student1.age)
print(student2.age)
student1.age = 28
print(student1.age)
print(student2.age)
20
25
28
25
我们发现当修改了student1的成员后,student2的成员并没有改变,这就说明同一个类的不同对象之间互不影响。
2、增加对象的成员,例子如下:
我们可以发现打印出了student1的weight成员为100,而打印student2时则会报错,这也说明同一个类的不同对象是互不影响的。
1.3 私有成员与公有成员
定义类或者对象的成员时,如果成员名是以两个下划线(__)开头则表示是私有成员。私有成员在类的外部不能直接访问,一般是在类的内部进行访问和操作,或者在类外部通过调用对象的公有成员方法来访问。但可以通过"类名/对象名._类名_xxx"来访问私有成员,但是一般不要这样做,会破坏类的封装性。
1.3.1 私有成员
1.3.1.1 类的私有成员
访问类的私有成员有三种方式:
1、内部访问
2、通过方法访问(类方法、静态方法、实例方法)
3、通过"类名._类名__xxx"来访问
1、先看一下从内部访问:
class Student(object):
__age = 20
print(__age)
__age = 25
print(__age)
20
25
因为定义类会运行类内部的代码,上面代码实现了从内部访问和修改。
2、下面看一下通过方法访问:
class Student(object):
__age = 20
# 对象的实例方法
def show1(self):
return(Student.__age)
# 类方法
@classmethod
def show2(cls):
return(cls.__age)
# 静态方法
@staticmethod
def show3():
return(Student.__age)
# 用实例化对象访问
student = Student()
print(student.show1())
print(student.show2())
print(student.show3())
# 分隔
print()
# 调用类方法访问
print(Student.show2())
# 分隔
print()
# 调用静态方法访问
print(Student.show3())
20
20
20
20
20
关于方法的调用,下面会讲解,这里只说明访问类的私有成员,可以采用这种方法。
3、通过"类名/对象名._类名__xxx"来访问
class Student(object):
__age = 20
print(Student._Student__age)
20
1.3.1.2 对象的私有成员
访问类的私有成员有三种方式:
1、内部访问
2、通过实例方法访问
3、通过"对象名._类名__xxx"来访问
1、从内部访问
class Student(object):
def __init__(self,age = 20): # 构造函数
self.__age = age
print(self.__age)
student = Student()
20
2、通过实例方法访问
class Student(object):
def __init__(self,age = 20): # 构造函数
self.__age = age
def show(self): # 实例方法
return(self.__age)
student = Student()
print(student.show())
20
3、通过"对象名._类名__xxx"来访问
class Student(object):
def __init__(self,age = 20):
self.__age = age
student = Student()
print(student._Student__age)
20
1.3.2 公有成员
公有成员是可以公开使用的,既可以在类的内部进行访问,也可以在外部程序中使用,看一下下面的例子:
class Student(object):
age = 20 # 类成员
print(age) # 访问类的成员
def __init__(self,height=180):
self.height = height # 对象成员
# 分隔符号
print()
# 类访问类的成员
print(Student.age)
# 类的实例化
student = Student()
# 分隔符号
print()
# 对象访问类成员
print(student.age)
# 对象访问对象的成员
print(student.height)
20
20
20
180
我们可以看到既可以在类内部访问,又可以在外部直接访问。
1.3.3 特殊成员
Python中以以下划线开头和结尾的成员名有特殊的意义,属于特殊成员。
1、_ xxx:保护成员,只有类对象和子类对象可以访问这些成员
2、__ xxx __:系统定义的特殊成员
2、__xxx:类中的私有变量,一般只能类对象自己访问,子类对象也不能访问。
二、类与对象的方法
方法用来描述类与对象所具有的行为,例如字符串对象的拼接、删除,文件对象的打开和关闭等等。在Python中方法可以大致分为四大类:公有方法、私有方法、静态方法和类方法。公有方法和私有方法一般属于对象的实例方法,静态方法和类方法都可以通过类名和对象名调用。
2.1 类方法与静态方法
2.1.1 类方法
类方法需要用装饰器 @classmethod 来修饰,一般将 cls 作为类方法的第一个参数,表示类本身,在调用类方法时不需要为该参数传值,例子如下:
class Student(object):
age = 20
@classmethod
def show(cls):
return(cls.age)
# 通过类名调用类方法
print(Student.show())
# 通过对象名调用类方法
student = Student()
print(student.show())
20
20
我们可以通过类名或者对象名来调用类方法
2.1.2 静态方法
静态方法需要用装饰器 @staticmethod 来装饰,静态方法中则不需要绑定类,也相当于是一个函数,在后面我们说一下函数与方法的区别。我们以一个例子来看一下:
class Student(object):
age = 20
@staticmethod
def show():
return(Student.age)
# 通过类名调用静态方法
print(Student.show())
# 通过对象名调用静态方法
student = Student()
print(student.show())
20
20
我们可以用类名或者对象名来调用静态方法
2.2 公有方法与私有方法
2.2.1 公有方法
公有方法通过对象名直接访问,但不可以用类名访问
1、我们看一下对象名访问
class Student(object):
def __init__(self,age): # 绑定实例属性
self.age = age
def show(self): # 公有方法
return(self.age)
# 类的实例化
student = Student(20)
# 通过对象名调用公有方法
print(student.show())
20
2、下面我们看一下类名访问
直接访问会报错,我们可以采取另外一种方式
3、通过将对象作为一个参数传入,则可使用
class Student(object):
def __init__(self,age=20): # 绑定实例属性
self.age = age
def show(self): # 公有方法
return(self.age)
student = Student()
print(Student.show(student))
20
因为self参数相当于是对象本身,所以可以这样调用
2.2.2 私有方法
私有方法不能通过对象名直接调用,只能在实例方法中通过self调用或者在外部用Python支持的特殊方式使用
1、从内部访问,可以用self调用
class Student(object):
def __init__(self,age=20): # 绑定实例属性
self.age = age
def __show(self): # 公有方法
return(self.age)
def fun(self):
print(self.__show())
student = Student()
print(student.fun())
20
可以将方法绑定到对象上,然后在内部进行访问
2、从外部访问,可以通过_对象名__方法名访问
class Student(object):
def __init__(self,age=20): # 绑定实例属性
self.age = age
def __show(self): # 公有方法
return(self.age)
student = Student()
print(student._Student__show())
20
三、方法与函数的区别
在Python中,函数与方法是有区别的。方法一般指与类或对象绑定的函数,通过类或对象调用方法时,类或对象本身将被作为第一个参数传递过去,普通函数没有这个特点。
3.1 类中的函数与方法
3.1.1 类中的函数
在Python中,类方法中的静态方法实际就是函数,下面我们以一个例子来说明
class Student(object):
pass
@staticmethod # 静态方法不与类绑定,相当于函数
def fun(age):
Student.age = age
Student.fun = fun # 动态增加函数
print(Student.fun) # 查看类型
Student.fun(35) # 传入参数
print(Student.age) # 打印值
<function fun at 0x000001C64280B7B8>
35
我们可以看到它的类型是一个function,而不是绑定类的方法。
3.1.2 类中的方法
class Student(object):
pass
@classmethod # 类方法与类绑定
def fun(cls,age):
cls.age = age
Student.fun = fun # 动态增加方法
print(Student.fun) # 查看类型
Student.fun(35) # 传入参数
print(Student.age) # 打印值
<bound method fun of <class '__main__.Student'>>
35
我们查看它的类型,可以发现它是一个绑定在类上的方法,可以通过这种方法动态增加类的方法
3.2 对象中的函数与方法
3.2.1 对象中的函数
class Student(object):
pass
def fun(self,age): # 定义一个函数
self.age = age
student = Student()
student.fun = fun # 直接赋值的话,相当于是一个函数,这点与类不同
print(student.fun) # 打印类型
student.fun(student,45) # 传入参数时,必须传入对象名称,因为它是一个函数
print(student.age)
<function fun at 0x000001C6429B2048>
45
打印它的类型,我们可以发现它是一个函数,调用时必须要把对象作为第一个参数传入。
3.2.2 对象中的方法
动态给对象绑定方法需要用到 types库,调用types.MethodType(方法名,对象名)来绑定
import types
class Student(object):
pass
def fun(self,age): # 定义一个函数
self.age = age
student = Student()
student.fun = types.MethodType(fun,student) # 第一参数为需要绑定的方法,第二个参数为对象名称
print(student.fun) # 打印类型
student.fun(45) # 传入参数时,不需要传入对象名称,因为它是一个方法
print(student.age)
<bound method fun of <__main__.Student object at 0x000001C642F2EB70>>
45
我们可以看到它的类型是一个绑定方法,调用时不需要传入对象名。