第六篇 面向对象
面向对象典型的语言就是Java
一.基本概念
__init__(cls):是对将来具体实例的初始化方法,一般是不需要写的,Python会自动执行 __new__(self): 对__init__生成并返回的具体对象进行初始化 ---- 术语:构造函数 __del__(self):Python解释器自动执行的,在程序执行完后,Python解释器会自动执行,回收,释放内存的时候才会调用;一般情况下也是不需要写的,Python会自动执行 ---术语:析构函数 __super__: @classmethod ---修饰器 @staticmethod --- 修饰器 在类外面定义的变量就叫变量;在类里面定义的变量就叫属性 在类外面定义的函数就叫函数;在类里面定义的函数就叫方法
二.类的定义和调用
1. 基础语法
class LeiMing(): def __init__(self, canshu): self.canshu = canshu def fangfa(self): pass # 对象的使用 # 1. 初始化对象 a = LeiMing(1) # 2. 调用类中的方法 a.fangfa()
示例1:人类
# 定义了一个类,类型,不区分具体的对象个体 class Person(): # 在类里可以定义变量 age = 10 # 初始化对象(初始化函数) def __init__(self,age = None): if age is not None: self.age = age # self代表的是将来具体的person1 、person2 这样一个个具体的个体对象 # 在类里也可以定义函数 def speak(self): print("Hello") # 类的使用,person1 和 person2 就是对象,是一个个具体的人,每个人(对象)都有自己特有的特征 person1 = Person() print(person1.age) # 10 person1.speak() # Hello person1.age = 20 # 修改了person1的age print(person1.age) # 20 person2 = Person(30) print(person2.age) # 30 print(Person.age) # 10
示例2:猫
class Cat(): def __init__(self,age = 0, sex = "male"): self.age = age self.sex = sex def sleep(self): pass def eat(self): pass big_cat = Cat(6, 'male') er_cat = Cat(7, 'female') san_cat = Cat(7) print(big_cat.age, big_cat.sex) # 6 male print(er_cat.age,er_cat.sex) # 7 female print(san_cat.age,san_cat.sex) # 7 male
2.变量和类的属性
在类外面定义的变量就叫变量;在类里面定义的变量就叫属性
变量的查找顺序:变量-->类->基类
class Cat(): def __init__(self,age = 0, sex = "male"): self.age = age self.sex = sex def sleep(self): pass def eat(self): pass big_cat = Cat(6, 'male') er_cat = Cat(7, 'female') san_cat = Cat(7) big_cat.color = 'white' print(big_cat.color) # white # 是从big_cat的变量里取的值 print(er_cat.color) # AttributeError: 'Cat' object has no attribute 'color' # 因为er_cat没有定义它自己的变量color,类里也没有定义color,基类里也没有color,所以会报属性错误 # 变量的查找顺序:变量-->类->基类
class Cat(): color = 'BlACK' def __init__(self,age = 0, sex = "male"): self.age = age self.sex = sex def sleep(self): pass def eat(self): pass big_cat = Cat(6, 'male') er_cat = Cat(7, 'female') san_cat = Cat(7) big_cat.color = 'white' print(big_cat.color) # white # 是从big_cat的变量里取的值 print(er_cat.color) # BlACK # er_cat没有定义自己的color,就从类里找属性,找到了BLACK
3. 类的方法
在类外面定义的函数就叫函数;在类里面定义的函数就叫方法
函数和方法的使用没有任何区别,只是方法的第一个参数是self
class Cat(): # 类的属性, color, self.age 都是类里的变量,但是术语叫做属性 color = 'BlACK' def __init__(self,name,age = 0, sex = "male"): self.age = age self.sex = sex self.name = name # 类的方法 def sleep(self): print("{} sleep".format(self.name)) # self.name:就是将来那个对象个体的名字,比如可以是damao,ermao,sanmao的名字 def eat(self): print("{} eat".format(self.name)) big_cat = Cat('damao',6, 'male') er_cat = Cat('ermao',7, 'female') san_cat = Cat('sanmao',7) # 类方法的调用 big_cat.sleep() # damao sleep er_cat.eat() # ermao eat
三.面向对象中的内置方法
1. 构造方法 与 析构方法
class Dog(object): # __init__的作用:是给具体对象dog进行初始化的 def __init__(self): # self代表的是将来的具体的对象个体 print("__init__") # __new__方法的作用:就是用类型(Dog)生成具体对象(dog)的,通常是不需要写的
# 构造方法
def __new__(cls): # cls代表的是当前的这个类,这里就是Dog这个类 print("__new__") # 作用:回收 # 是Python解释器自己调用执行的
# 析构方法
def __del__(self): print("__del__") def speak(self): print("我啥都不想说") dog = Dog() dog.speak() # 报错 ''' AttributeError: 'NoneType' object has no attribute 'speak' 在上面的Person和Cat类里,没有__new__方法,就可以正常执行,而这里有 __new__ 方法,就报错了,为什么? '''
class Dog(object): # __init__的作用:是给具体对象dog进行初始化的 def __init__(self): # self代表的是将来的具体的对象个体 print("__init__") # __new__方法的作用:就是用类型(Dog)生成具体对象(dog)的,通常是不需要写的 def __new__(cls): # cls代表的是当前的这个类,这里就是Dog这个类 print("__new__") return object.__new__(cls) # 这里是通用写法,而且写了一定要返回 # 作用:回收 # 是Python解释器自己调用执行的,一般也是不需要写的 def __del__(self): print("__del__") def speak(self): print("我啥都不想说") dog = Dog() dog.speak() # 输出 __new__ __init__ 我啥都不想说 __del__ ''' 看上面输出的代码的执行顺序 1. 先执行__new__ 2. 再执行__init__ 3. 接着执行函数方法 4. 等所有逻辑执行完成后,最后执行__del__,回收,释放内存 '''
四. 继承与super函数
class Fish(object): # Fish继承了Python的基类 def __init__(self,name): self.name = name def bubble(self): print("我叫{}: 我吐一串泡泡".format(self.name)) def swam(self): print("我是{}我游得很快".format(self.name)) # 定义一个多宝鱼,继承鱼类 class Turbot(Fish): def __init__(self,name): super(Turbot,self).__init__(name) # 固定写法: # 1. super()函数的第一个参数是类型(类名),第二个参数是对象 # 2 super()函数写在哪个类里面,第一个参数就是哪个类的类名,第二个参数是对象,对象是self; # 3. super()后面调用的是父类的方法,此处是父类(Fish类)的初始化方法__init__(name) # super()函数的本质:是调用它继承的那个类(即父类)里的方法或者属性 # super()函数的作用:可以一次性调用所有父类 def run(self): # 多宝鱼没有跑方法,但是可以通过super调用父类的swam方法,那多宝鱼也有了游的方法 super(Turbot,self).swam() fish = Turbot("多宝鱼") fish.swam() fish.bubble() fish.run()
五. 类的修饰器 @classmethod 和 @staticmethod
class Fish(object): # Fish继承了Python的基类 def __init__(self,name): self.name = name def bubble(self): print("我叫{}: 我吐一串泡泡".format(self.name)) def swam(self): print("我是{}我游得很快".format(self.name)) # 定义一个多宝鱼,继承鱼类 class Turbot(Fish): def __init__(self,name): super(Turbot,self).__init__(name) # 固定写法: # 1. super()函数的第一个参数是类型(类名),第二个参数是对象 # 2 super()函数写在哪个类里面,第一个参数就是哪个类的类名,第二个参数是对象,对象是self; # 3. super()后面调用的是父类的方法,此处是父类(Fish类)的初始化方法__init__(name) # super()函数的本质:是调用它继承的那个类(即父类)里的方法或者属性 # super()函数的作用:可以一次性调用所有父类 # 类方法里面的self参数代表具体对象本身 def run(self): # 多宝鱼没有跑方法,但是可以通过super调用父类的swam方法,那多宝鱼也有了游的方法 super(Turbot,self).swam() # 类方法里面的cls参数,代表的是类(这里是Trubot这个类)本身 # 想代表类本身的时候,它就是个类方法,类方法可以用@classmethod去修饰,而用@classmethod修饰的类方法,可以直接用 # 类名.方法名调用 或者 对象.方法名 @classmethod def balabala(cls): print("balabala") # 静态方法:可以认为与外面的函数是等价的,是一个普通函数,因为完全不需要用self或者cls去修饰 # 静态方法:可以在任何时候调用 # 调用方法:类名.方法名() # 用静态方法修饰后,可以理解为既不属于这个类,也不属于self那个对象,只是把这个方法写在了类里面而已 # 静态方法是独立于各种类以外的 @staticmethod def kalakala(): # 静态方法,可以没有cls参数 print("kalakala") fish = Turbot("多宝鱼") Turbot.balabala() # 类可以直接调用被@classmethod修饰过的类方法 Turbot.kalakala() # 类可以直接调用被@staticmethod修改过的方法 fish.balabala() # 对象可以调用被@classmethod修饰过的类方法 fish.kalakala() # 对象可以调用被@staticmethod修改过的方法
练习:实现水果类,并通过继承方法实现苹果,梨,香蕉和西瓜类
class Fruit(object): def __init__(self,name,price): self.name = name self.price = price class Apple(Fruit): def __init__(self,name,price): super(Apple,self).__init__(name,price) class Peer(Fruit): def __init__(self,name,price): super(Peer,self).__init__(name,price) class Banana(Fruit): def __init__(self,name,price): super(Banana, self).__init__(name,price) class Watermelon(Fruit): def __init__(self,name,price): super(Watermelon, self).__init__(name,price)
六. 总结
一. 类中__new__() 和 __init__()的区别是什么?
1.__new__()方法是把类型创建为具体的对象;__init__()是给具体的对象进行初始化的
2. __init__()要想初始化具体的对象,必须通过__new__先创建一个对象,并且要在__new__返回这个对象后,__init__()才能知道该去初始化谁。
通过new生成对象,然后要返回对象,这是通用写法;
object也是类,object是Python的最根本的类型,生成一个新的对象都是根据object来生成 的;
所以上面示例中dog这个具体的对象是__new__生成的,而不是__init__生成的;
通常情况下,__new__是不需要写的,Python会自动给每个来加一个__new__方法;
3. 执行顺序一定是先执行__new__,后执行__init__