类包括属性和功能(方法),在使用类时,需要先定义类,然后再创建类的实例,通过类的实例就可以访问类中的属性和方法了。
类用class创建,后面的类名通常首字母大写,
# 类对象
class Student:
'''类的说明文档'''
pass
实例化:将抽象的类对象的概念具象化的步骤称为实例化,即实例化对象
#实例化
类名+()
# 例如
stuednt() # 类似于函数的调用
# 用一个东西来接受
stu1 = student()
特殊方法(魔术方法):以__开头,并且以__结尾的方法(特点:不需要主动去调用,在特定情况下会被自动调用)
当实例化的时候,会自动调用__new__(cls);
__new__(cls):把实例化类对象(即Student)和实例化传入的实参一起打包,作为实参传给cls,然后__new__会根据该类对象去创建一个实例对象,然后把该实例对象和打包的其他实参,作为实参传给__init__(self)(self形参接受了实例参数),然后通过__init__方法对该实例对象,进行一系列的定制化操作,(比如定制属性),最后__new__把__init__定制好的该实例对象进行返回;
__new__(cls):又称构造方法:返回的一定是一个实例对象,其必须要有一个参数cls,代表着要实例化的类,而且必须要有返回值,返回实例化出来的实例对象,在此场景下,cls中为类名Student ;
__init__(self):又称初始化方法:被__new__(cls)调用,可以被人认为实例化时自动调用,即self形参接收了实例对象,通过__init__对该实例对象进行一系列定制操作(定制属性),然后通过__new__(cls)把__init__定制好的实例对象返回,返回给调用方student(),然后用stu1接收,__init__(self)返回None;
__init__(self):可以传多个参数,但是第一个必须是self;
实例对象是构造方法和初始化方法共同定制的
# 例如
class Student:
def __init__(self, name, age): # 定义两个形参
self.name = name
self.age = age
stud1 = Student('张三', 18) # 传入两个实参
stud2 = Student('李四', 28) # 两次实例化创建的实例对象不一样,不是一个东西,不同的定制
print(stud1)
print(stud2)
# 终端显示
<__main__.Student object at 0x000001CDFB18A430>
<__main__.Student object at 0x000001FE8BC3A340>
默认所有的类都继承object类,此时把object类称为父类/基类/超类,通常可以省略不写
如果写的话,应该是:
class Student(object):
为什么没有按照《2、实例化》中说的先调用__new__(cls),然后再调用__init__(self),而是直接调用__init__(self),是因为在其父类object中有__new__(cls)
按Ctrl左击object,可以看到有__new__(cls)和__init__(self),因此不需要再写__new__(cls),系统会自动调用父类的__new__(cls)
同时也看到父类里面有__init__(self),为什么还要写__init__(self)呢,是因为父类的__init__(self)不能实现定制,父类的__init__(self)只有self,没有其他形参,无法更改
如果不需要定制属性,只做实例化,那么可以直接使用父类的__init__(self);
类名+括号:实例化Student()
实例化得到实例对象
# 例如
print() # 调用函数
int() # 实例化
int(9.12) #得到的9,就是实例对象,是int类的实例对象
实例属性是每个实例对象所独有的,类属性是实例对象所共有的
# 例如
class Student(object):
school = '3年2班' # 添加类属性
def __init__(self, name, age):
self.name = name
self.age = age
属性调用规则:
# 例如
class Student(object):
school = '3年2班'
def __init__(self, name, age):
self.name = name
self.age = age
stud1 = Student('张三', 18)
stud2 = Student('李四', 28)
print(stud1.name) # 只能用实例对象调用实例属性
print(stud1.age)
print(Student.school) # 用类对象调用类属性
print(stud2.school) # 用实例对象调用类属性(如果实例对象没有该属性,则会调用类属性)
# 终端显示
张三 # stud1实例属性
18 # # stud1实例属性
3年2班 # 类属性
3年2班 # 类属性
# 例如
class Student(object):
school = '3年2班'
def __init__(self, name, age):
self.name = name
self.age = age
self.school = '5年4班'
stud1 = Student('张三', 18)
stud2 = Student('李四', 28)
print(stud1.school) # 如果实例属性被写死了,那么实例对象只能调用实例属性
print(Student.school)
# 终端显示
5年4班
3年2班
动态定义变量(增加属性)
修改属性
# 例如
class Student(object):
school = '3年2班'
def __init__(self, name, age):
self.name = name
self.age = age
self.school = '5年4班'
stud1 = Student('张三', 18)
stud2 = Student('李四', 28)
print(stud1.age)
stud1.age = 20 # 实例属性的修改
print(stud1.age)
stud1.sex = 'man' # 如果该实例属性在实例对象里面没有,则会增加该属性
print(stud1.sex)
print(Student.school)
Student.school = '六年级六班'
print(Student.school)
Student.classmate = 56 # 如果该类属性在类里面没有,则会增加该类属性
print(Student.classmate)
print(stud1.age) # 实例属性删除前
del stud1.age # 删除实例属性
print(stud1.age) # 实例属性删除后
print(Student.school) # 类属性删除前
del Student.school # 删除类属性
print(Student.school) # 类属性删除后
# 终端显示
18 # 实例属性修改前
20 # 实例属性修改后
man # 实例属性动态定义变量
3年2班 # 类属性修改前(类属性的修改只能通过访问类属性来修改,不能通过访问实例属性来修改)
六年级六班 # 类属性修改后
56 # 类属性增加后
20 #实例属性删除前
AttributeError: 'Student' object has no attribute 'age' # 实例属性删除后,报错
六年级六班 # 类属性删除前
AttributeError: type object 'Student' has no attribute 'school' #类属性删除后,报错