一、面向对象
- 是一种认识世界,分析世界的方法论,将万事万物抽象为类
1、类class
- 类是抽象的概念,是万事万物的抽象,是一类事物的共同特征的集合,用计算机语言来描述类,就是属性和方法的集合
2、对象instance,object
- 对象是类的具象,是一个实例
- 对于我们每个人这个个体,都是抽象概念人类的不同的实体
- 对象属性:它是对象状态的抽象,用数据结构来描述
- 对象操作:它是对象行为的抽象,用操作名和实现该操作的方法来描述
3、面向对象三要素
- 封装:将数据和操作组装到一起,起到隐藏数据,对外只暴露一些接口通过接口访问对象
- 继承:多复用,继承来的就不用自己写了,多继承少修改,使用继承来改变,来体现个性
- 多态:面向对象编程最灵活的地方,动态绑定
举例: class Myclass: """A example class""" x = 'abc' #类属性 def foo(self): #类属性也是方法 return 'My Class'
4、类对象及类属性
- 类对象,类的定义就会生成一个类对象
- 类的属性,类定义中的变量和类中定义的方法都是类的属性
- 类变量,x是类Myclass的变量
5、类的实例化
- a = Myclass()
- 类实例化后获得的实例,是不同的实例,即使是使用同样的参数实例化,也得到不一样的对象
- python类实例化后,会自动调用__init__方法,这个方法第一个参数必须留给self
6、__init__方法
- Myclass()实际上调用的是__init__(self)方法,可以不定义,如果没有定义会在实例化后隐式调用
- 作用是对实例进行初始化
- __init__()方法不能有返回值,也就是只能是None
举例: class Person: def __init__(self, name, age): self.name = name self.age = age def showage(self): print('{} is {}'.format(self.name,self.age)) tom = Person('Tom',20)
7、实例对象instance
- 类实例化后一定会获得一个对象,就是实例对象
- __init__方法的第一个参数self就是指代某一个实例
- 类实例化出一个实例对象,实例对象会绑定方法,调用方法是采用tom.showage()方式
- 这个self就是tom,python会把方法的调用者作为第一参数self的实参传入
- self.name就是tom对象的name,name是保存在了tom对象上,而不是在Person类上,所以称为实例变量
8、实例变量和类变量
- 实例变量是每个实例自己的变量,是自己独有的;
- 类变量是类的变量,是类所有实例共享的变量属性和方法
class Person; age = 3 # 类变量 def __init__(self, name, age): self.name = name # 实例变量 self.age = age print(Person.__class__) print(sorted(Person.__dict__.items()) #属性字典 tom = Person('Tom',20) print(tom.__class__) print(sorted(tom.__dict__.items()))
上例中,可以看到类属性保存在类的__dict__中,实例属性保存在实例的__dict__中,如果从实例访问类的属性,就需要借助__class__找到所属的类
9、类和实例
- 是类的,也是这类的所有实例的,其实例都可以访问到,是实例的就是这个实例自己的,通过类访问不到
- 类变量是属于类的变量,这个类的所有实例可以共享这个变量
- 实例可以动态的给自己增加一个属性,实例__dict__和实例变量都可以访问到
- 实例的同名变量会隐藏这个类变量,或者说是覆盖了这个类变量
10、实例属性的查找顺序
- 指的是实例使用点来访问属性,会先找自己的__dict__,如果没有,然后通过属性__class__找到自己的类,再去类dict中找
- 注意,如果实例使用__dict__[变量名]访问变量,将不会按照上面的查询顺序找变量
二、类方法和静态方法
- 前面的例子中定义的__init__等方法,这些方法本身都是类属性,第一个参数必须是self
- self必须指向一个对象,也就是类必须实例化之后,由实例来调用这个方法
1、普通函数调用
class Person: def normal_method(): print('normal') Person.normal_method() # 可以调用 Person().normal_method() #不能调用 Person.normal_method()可以调用,因为这个方法只是被Person这个名词空间管理的一个普通方法 normal_method只是Person的一个属性而已 由于normal_method在定义的时候没有指定self,所有不能完成实例对象的绑定,不能通过实例化来调用
2、类方法
- 在类定义中,使用@classmethod装饰器修饰的方法,必须至少有一个参数,且第一个参数留给了cls,cls指代调用者即类对象自身
- cls这个标识符可以是任意合法名称,但是为了易读,请不要修改
- 通过cls可以直接操作类的属性
举例: class Person: @classmethod def class_method(cls): print('class = {0.__name__} ({0})'.format(cls)) cls.HEIGHT = 170 Person.class_method() print(Person.__dict__) >>> Person.class_method() class = Person (<class '__main__.Person'>) >>> print(Person.__dict__) {'__module__': '__main__', '__weakref__': <attribute '__weakref__' of 'Person' objects>, '__doc__': None, 'HEIGHT': 170, '__dict__': <attribute '__dict__' of 'Person' objects>, 'class_method': <classmethod object at 0x00000000030783C8>}
3、静态方法
- 在类的定义中,使用@staticmethod装饰器修饰的方法
- 调用时,不会隐式的传入参数,静态方法只是表明这个方法属于这个名词空间
class Person: @classmethod def class_method(cls): print(11111,'class = {0.__name__} ({0})'.format(cls)) cls.HEIGHT = 170 @staticmethod def static_method(): print(2222222,Person.HEIGHT) Person.class_method() Person.static_method() print(333333333,Person.__dict__) 类除了普通方法都可以调用,普通方法需要对象的实例作为第一参数 实例可以调用所有类中定义的方法(包括类方法,静态方法),普通方法传入实例自身 静态方法和类方法需要找到实例的类