第六篇 面向对象

面向对象典型的语言就是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__

posted @ 2019-08-05 17:08  mamingchen  阅读(230)  评论(0编辑  收藏  举报