定义类时如果不指定父类,py3.x会默认继承自基类object,它有一些内置的以__开头和结尾的属性和方法,但py2.x不会以object为基类,因此为了保证通用性,如果没有父类,应显式继承object类;
dir(对象名) # 查看该对象拥有的所有属性和方法
- 定义类
类名:大驼峰
方法:和常规函数相比,第一个参数必须是self
- 创建类对象:
tom = Cat() # 创建一个Cat对象tom
实际做了两件事:
1.为对象在内存中分配空间
2.调用初始化方法__init__(),初始化类对象的属性值
- 实例属性:两种方法
在类的内部添加实例属性:在__init__方法内定义
class Cat(object):
def __init__(self, name):
self.name = name # 该类的所有实例化对象都拥有name属性
在类的外部添加实例属性:实际只是为单个类对象添加了
class Cat(object):
def eat(self):
print(self.name)
tom = Cat()
tom.name = "Tom" # 只有tom这个实例化对象有name属性
tom.eat() # "Tom"
c = Cat()
c.eat() # 报错,c没有name属性,因此eat方法中self.name访问失败
- 类的内置方法和属性
__init__():构造函数,创建类对象时被调用
__del__()方法:析构函数,在对象从内存销毁前,会被自动调用
__str__()方法:必须返回一个字符串,当print(类对象)时,会打印这个自定义字符串
- 如果类中的属性暂时不知道初始值,可以初始化为None,针对None比较时,一般用is;
- is和is not:比较的是所引用对象的地址
is: x is y, 等价于id(x) == id(y), 即判断两个变量是否引用同一对象
is not: 同理
==:判断引用变量的值是否相等
- 定义私有属性和方法:在名字前增加两个下划线(等价于C++的private),Py的解释器会将私有属性__变量名 解释为 _类名__变量名, 外界就无法访问到了
class People:
def __init__(self, name):
self.name = name
self.__age = 18
lx = People("lxxx")
print(lx._People__age) # 在外部可以通过这种方法强行访问私有属性和方法, 但一般不要用
- 继承:父类拥有子类的所有属性和方法
class 类名(父类名):
pass
- 重写
1.覆盖父类的方法:在子类中定义一个与父类同名的方法,给一个不同的实现(完全重写)
2.对父类方法进行扩展:在子类中定义一个与父类同名的方法,在需要的位置使用super().父类方法, 来调用父类方法
super():super类的一个临时对象,super.().父类方法作用就是调用父类的某个方法
在py2.x中,还可以使用父类名.父类方法(self),但父类名修改后,子类中也需要修改(不推荐)
- 在子类方法中,可以通过调用父类的公有方法来间接访问到父类的私有属性和私有方法
1.父类的公有方法可以访问自己的私有属性和私有方法
2.子类可以调用父类的公有方法,但无法访问父类的私有属性和私有方法
- 多继承
class 类名(父类名1, 父类名2, ...):
pass
如果父类之间存在同名属性或方法,应避免多继承它们;
- MRO:方法搜索顺序(method resolution order),用于在多继承时判断方法,属性的调用路径
print(类名.__mro__) # py针对类有一个内置属性__mro__,可以查看方法搜索顺序, 会按照这个顺序依次搜索调用的方法
-
多态
很简单,不多描述 -
类属性:在类外部可以通过类名.或类对象名.访问
class Tool:
count = 0 # 类属性
def __init__(self, name):
Tool.count += 1
tool1 = Tool("111")
tool2 = Tool("222")
print(tool1.count) # 2
print(tool2.count) # 2
print(Tool.count) # 2
类方法:在方法内部,只需要访问类属性/方法;
class Tool:
count = 0 # 类属性
def __init__(self, name):
Tool.count += 1
@classmethod
def show(cls):
print(cls.count) # 在类方法内部,可以使用cls访问类属性或类方法
tool1 = Tool("111")
tool2 = Tool("222")
# 在类外部,可以使用类名或类对象名调用类方法
tool1.show() # 2
tool2.show() # 2
Tool.show() # 2
- 静态方法:在方法内部,无需访问实例属性/方法和类属性/方法;
class Dog:
@staticmethod # 告诉解释器这是个静态方法
def run(): # 不需要访问实例属性/方法
print("小狗跑...")
# 静态方法可以通过类名或实例化对象调用
Dog.run() # 小狗跑...
dog = Dog()
dog.run() # 小狗跑...