技术交流QQ群:1027579432,欢迎你的加入!
1.类和实例
- 类是抽象的模板,实例是根据类创建出来的一个个具体的"对象"。例如:动物是一大类,猫、狗、鱼等都是特定的对象,即实例。python3中使用class关键字来定义类,基本结构如下:
class 类名(父类/基类/超类列表):
pass
- 类名一般使用大驼峰来进行命名,尽量见名知意。python采用多继承的机制,一个类可以同时继承多个父类(基类、超类),继承的父类有先后顺序,写在类名后面的括号中。python3中,object是python3中所有类的基类中,可以省略类名后面的括号,表示隐式继承。
- 通过类的实例化方法来创建一个类的实例,类似于C++中的构造函数。默认情况下,使用类似stu = Student()的方式就可以生成一个类的实例。但是,实际中一个类的实例也会有属于自己的实例变量。python中提供一个def __init__(self):实例化机制。任何一个类中,名字为__init__()的方法就是类的实例化方法。具有__init__()方法的类在类进行实例化时,会自动调用此方法,并传递对应的参数。如下面所示:
class Student:
def __init__(self,name, age):
self.name = name
self.age = age
def printInfo(self):
print("name:{}".format(self.name), "age:{}".format(self.age))
stu1 = Student("curry", 31)
stu2 = Student("harden", 29)
2.实例变量与类变量
- 实例变量:实例本身所拥有的变量,每个实例的变量在内存中都不一样。调用方法:实例名.实例变量名
stu1.name
stu1.age
- 类变量:定义在类中,但在方法之外的变量。可以通过类名.类变量名或者实例名.类变量名来访问类变量。类变量是所有实例都共同拥有的变量,每个实例都可以访问、修改类变量。例如下面例子中,classroom和address就是两个类变量。注意:当使用stu1.name访问变量时,实例会首先在自己的实例变量中查找是否有此实例变量name,然后再去类变量中进行查找,如果都没有,则抛出异常!
class Student:
classroom = "101"
address = "beijing"
def __init__(self,name, age):
self.name = name
self.age = age
def printInfo(self):
print("name:{}".format(self.name), "age:{}".format(self.age))
stu1.classroom # 类变量的访问
Student.classroom
stu1.name
- 因为Python是动态语言的特点,可以随时给实例动态添加新的实例变量,给类添加新的类变量和方法。因此,使用stu1.classroom="110"时,要么是给已有的实例变量classroom重新赋值,要么就是新建一个专属于stu1实例的实例变量,并赋值110,如下面的例子:
class Student:
classroom = "101" # 类变量
address = "beijing"
def __init__(self,name, age):
self.name = name
self.age = age
def printInfo(self):
print("name:{}".format(self.name), "age:{}".format(self.age))
stu1 = Student("curry", 31)
stu2 = Student("harden", 29)
print(stu1.classroom) # stu1实例本身没有classroom实例变量,所以去寻找类变量,它找到了!
Student.classroom # 通过类名访问类变量
stu1.classroom = "110" # 关键的一步!实际是为实例stu1创建了一个独有的实例变量classroom,只不过名字和类变量一样,都叫做classroom。
print(stu1.classroom) # 输出110,再次访问的时候,访问到的是stu1自己的实例变量classroom
del stu1.classroom # 删除了stu1的实例变量classroom
3.类的方法
- Python的类中包含实例方法、静态方法和类方法三种方法。
- 实例方法:类的实例方法由实例调用,至少包含一个self参数,且为第一个参数。执行实例方法时,自动将调用该方法的实例赋值给self。self代表的是类的实例,而非类本身。self不是关键字,而是Python约定成俗的命名,你完全可以取别的名字,但不建议这么做。 例如下面的方法printInfo(self):
def printInfo(self):
print("name:{}".format(self.name), "age:{}".format(self.age))
- 静态方法:静态方法由类调用,无默认参数。将实例方法参数中的self去掉,然后在方法定义上方加上@staticmethod,就成为静态方法,它属于类,和实例无关。建议只使用类名.静态方法调用方式。(虽然也可以使用实例名.静态方法的方式调用)
class Foo:
@statcimethod:
def static_method():
pass
# 调用
Foo.static_method()
- 类方法:类方法由类调用,采用@classmethod装饰,至少传入一个cls(代指类本身,类似self)参数。执行类方法时,自动将调用该方法的类赋值给cls。建议只使用类名.类方法的调用方式。(虽然也可以使用实例名.类方法的方式调用)
class Foo:
@classmethod
def bar_method(cls):
pass
# 调用
Foo.bar_method()
- 综合实例如下:
class Foo:
def __init__(self,name):
self.name = name
def ord_func(self): # 定义实例方法,至少有一个self参数
print("实例方法")
@classmethod
def class_func(cls): # 定义类方法,至少有一个cls参数
print("类方法")
@staticmethod
def static_func(): # 定义静态方法 ,无默认参数
print("静态方法")
# 调用实例方法
f = Foo("Jack")
f.ord_func()
Foo.ord_func(f) # 请注意这种调用方式,虽然可行,但建议不要这么做!
# 调用类方法
Foo.class_func()
f.class_func() # 请注意这种调用方式,虽然可行,但建议不要这么做!
# 调用静态方法
Foo.static_func()
f.static_func() # 请注意这种调用方式,虽然可行,但建议不要这么做!
4.类、类的方法、类变量、类的实例和实例变量在内存中是如何保存的?
- 类、类的所有方法以及类变量在内存中只有一份,所有的实例共享它们。而每一个实例都在内存中独立的保存自己和自己的实例变量。创建实例时,实例中除了封装诸如name和age的实例变量之外,还会保存一个类对象指针,该值指向实例所属的类的地址。因此,实例可以寻找到自己的类,并进行相关调用,而类无法寻找到自己的某个实例。
5.参考博客