Python_07_面向对象

Python

基础

面向对象

面向对象基础
类和对象

是对一系列具有相同特征行为的事物的统称,是一个抽象的概念。例如:飞机的图纸。

特征:属性

行为:方法

对象

对象是类创建出来的真实存在的事物,例如:某架飞机。

实例

一般创建对象也叫实例化对象,即为一个实例。但有一种抽象对象,创建出的对象不是实例。

创建类和对象
创建类
def ClassName():
    pass
# 一般使用大驼峰命名。

PEP8中规范:

类名一般使用首字母大写的约定。
在接口被文档化并且主要被用于调用的情况下,可以使用函数的命名风格代替。
注意,对于内置的变量命名有一个单独的约定:大部分内置变量是单个单词(或者两个单词连接在一起),首字母大写的命名法只用于异常名或者内部的常量。

例:

class Washer():
    def wash(self):
        print("洗衣机洗衣服")

上例也定义了一个方法,方法的定义与函数基本相同。

创建对象
obj_name = ClassName()

例:

# 定义一个类
class Washer():
    def wash(self):
        print("洗衣机洗衣服")
# 创建对象
haier = Washer()
# 对象调用实例方法
haier.wash()

#输出
洗衣机洗衣服
self

self指的是调用该函数的对象,一般打印为内存地址。

对象不同,即内存地址不同,即self不同。

# 定义类
class Washer():
    def wash(self):
        print("洗衣机洗衣服")
        print(self)
# 创建2个对象
haier = Washer()
geli = Washer()
# 分别调用实例方法
haier.wash()
geli.wash()

#输出
洗衣机洗衣服
<__main__.Washer object at 0x000002264128BB20>
洗衣机洗衣服
<__main__.Washer object at 0x000002264128BB50>
属性
类外添加属性
obj_name.attribute = value

例:

# 使用上述Washer类
# 创建一个对象
haier = Washer()
haier.width = 500
haier.height = 800
类外获取属性
obj_name.attribute

例:

# 使用上述Washer类
# 使用上述haier实例和属性
print(haier.width)
print(haier.height)
#输出
500
800
类内获取对象属性
# 定义类
class Washer():
    def print_info(self):
        # 类里面获取实例属性
        print(self.width)
        print(self.height)

# 创建对象
haier1 = Washer()

# 添加实例属性
haier1.width = 500
haier1.height = 800

haier1.print_info()

#输出
500
800
魔法方法
_init_()

__init__()方法可以初始化属性。上述属性都是在类外定义的, 这个魔法方法可以让属性在类内初始化定义。

例:

# 定义一个类
class Washer():
    def __init__(self,width,height):
        self.width = width
        self.height = height
    def print_info(self):
        print(self.width)
        print(self.height)
# 创建一个对象,并使用实例方法
haier = Washer(500,800)
haier.print_info()

# 输出
500
800
# 不接受参数的初始化属性
class Washer():
    def __init__(self):
        self.width = 500
        self.height = 800
_str_()

通常用print打印对象的时候,会打印其内存地址。如果使用__str__()方法,可以打印该方法中返回的数据。

例:

# 定义一个没有__str__方法的类
class Washer():
    def __init__(self):
        self.width = 500
# 创建一个对象
haier = Washer()
# 打印这个对象
print(haier)

# 输出
<__main__.Washer object at 0x0000014A5051BFA0>
# 定义一个有__str__方法的类
class Washer():
    def __init__(self):
        self.width = 500
    def __str__(self):
        return "这是一个洗衣机"
# 创建一个对象
haier = Washer()
# 打印这个对象
print(haier)

# 输出
这是一个洗衣机
_del_()

当删除一个对象是,Python解释器会默认调用__del__()方法。

例:

# 定义一个没有__del__方法的类
class Washer():
    pass
# 创建一个对象
haier = Washer()
# 删除这个对象
del haier
# 定义一个有__del__方法的类
class Washer():
    def __del__(self):
        print("该对象已经被删除")
# 创建一个对象
haier = Washer()
# 删除这个对象
del haier
# 输出
该对象已经被删除
继承
继承
继承

继承通常为子女继承父母的财产。在面向对象编程中为子类继承父类的属性和方法。

新式类和旧式类

旧式类,或称经典类。不由任意内置类型派生出的类。已经被Python3.0以后的版本淘汰。

class ClassName():
    pass

新式类,继承自object类。object类为基类。子类也叫做派生类

class ClassName(object):
    pass
# Pyhton3.0以后的版本,默认继承object类,不写也会继承。
单继承和多继承
单继承

子类只继承一个父类,该种继承为单继承

例:

# 模拟一家有一个面条技术
# 定义一个父类
class Father(object):
    def __init__(self):
        self.recipe = "祖传面条配方"
    def make_noodles(self):
        print("使用"+self.recipe+"制作面条")
# 定义一个子类
class Son(Father):
    pass
# 使用子类创建一个对象,并调用父类方法和属性
jachin = Son()
print(jachin.recipe)
jachin.make_noodles()

#输出
祖传面条配方
使用祖传面条配方制作面条
多继承

一个子类继承了多个父类,为多继承

# 模拟一家有一个祖传面条配方
# 儿子还在学校外学了一个面条配方
# 定义父亲父类
class Father(object):
    def __init__(self):
        self.recipe = "祖传面条配方"
    def make_noodles(self):
        print("使用"+self.recipe+"制作面条")
# 定义学校父类
class School(object):
    def __init__(self):
        self.recipe = "通用面条配方"
    def make_noodles(self):
        print("使用"+self.recipe+"制作面条")

# 定义一个子类
class Son(School,Father):
    pass
# 使用子类创建一个对象,并调用父类方法和属性
jachin = Son()
print(jachin.recipe)
jachin.make_noodles()

# 继承多个父类,遇见同名属性和方法。
# 会默认调用第一个父类的属性和方法。
# 输出
通用面条配方
使用通用面条配方制作面条

继承多个父类,遇见同名属性和方法,会默认调用第一个父类的属性和方法。

重写父类同名属性和方法

子类和父类具有同名属性和方法,默认使用子类的同名属性和方法。

# 模拟一家有一个祖传面条配方
# 儿子还在学校外学了一个面条配方
# 现在儿子将两个配方研究,创造了自己独创的秘方。
# 定义父亲父类
class Father(object):
    def __init__(self):
        self.recipe = "祖传面条配方"
    def make_noodles(self):
        print("使用"+self.recipe+"制作面条")
# 定义学校父类
class School(object):
    def __init__(self):
        self.recipe = "通用面条配方"
    def make_noodles(self):
        print("使用"+self.recipe+"制作面条")

# 定义一个子类
class Son(School,Father):
    def __init__(self):
        self.recipe = "独创面条配方"
    def make_noodles(self):
        print("使用"+self.recipe+"制作面条")
# 使用子类创建一个对象,并调用父类方法和属性
jachin = Son()
print(jachin.recipe)
jachin.make_noodles()

#输出
独创面条配方
使用独创面条配方制作面条
__mro__属性

__mro__属性可以查看该对象所属类的继承关系。该算法用拓扑排序构成。

class X(object):pass
class Y(object):pass
class A(X, Y):pass
class B(Y):pass
class C(A, B):pass
print(C.__mro__)
#输出
(<class '__main__.C'>, <class '__main__.A'>, <class '__main__.X'>, <class '__main__.B'>, <class '__main__.Y'>, <class 'object'>)
调用父类同名属性和方法

如果子类仍然想调用父类的方法,可以重新写一个方法,让该方法调用父类的方法。但要注意,调用父类的属性则需要用父类重新初始化。

# 模拟一家有一个祖传面条配方
# 儿子还在学校外学了一个面条配方
# 现在儿子将两个配方研究,创造了自己独创的秘方。
# 儿子目前会三种配方,顾客需要哪个就用哪个。
# 定义父亲父类
class Father(object):
    def __init__(self):
        self.recipe = "祖传面条配方"
    def make_noodles(self):
        print("使用"+self.recipe+"制作面条")
# 定义学校父类
class School(object):
    def __init__(self):
        self.recipe = "通用面条配方"
    def make_noodles(self):
        print("使用"+self.recipe+"制作面条")

# 定义一个子类
class Son(School,Father):
    def __init__(self):
        self.recipe = "独创面条配方"
    def make_noodles(self):
        self.__init__()
        print("使用"+self.recipe+"制作面条")
    def make_father_noodles(self):
        Father.__init__(self)
        Father.make_noodles(self)
    def make_school_noodles(self):
        School.__init__(self)
        School.make_noodles(self)

# 使用子类创建一个对象,并调用父类方法和属性
jachin = Son()
print(jachin.recipe)
jachin.make_noodles()
jachin.make_father_noodles()
jachin.make_school_noodles()

# 输出
独创面条配方
使用独创面条配方制作面条
使用祖传面条配方制作面条
使用通用面条配方制作面条
super()

上条调用父类的属性和方法虽然能实现,但是如果更改父类的类名,便需要大量修改代码,造成了代码的冗余。并且,当出现多继承时,都调用父方法,会出现钻石继承的问题。

故可以使用super()函数减少冗余。

super()若不传入参数,便会根据__mro__属性的顺序选择第一个有相同方法的父类进行方法调用。

super()若传入参数,第一个参数为自己或一个父类名,第二个参数为self。若选择一个父类名,那么调用顺序就从__mro__属性中找到该父类名,按顺序从它下一个类开始选择。

例:

# 模拟一家有一个祖传面条配方
# 儿子还在学校外学了一个面条配方
# 现在儿子将两个配方研究,创造了自己独创的秘方。
# 儿子目前会三种配方,顾客需要哪个就用哪个。
# 定义父亲父类
class Father(object):
    def __init__(self):
        self.recipe = "祖传面条配方"
    def make_noodles(self):
        print("使用"+self.recipe+"制作面条")
# 定义学校父类
class School(object):
    def __init__(self):
        self.recipe = "通用面条配方"
    def make_noodles(self):
        print("使用"+self.recipe+"制作面条")

# 定义一个子类
class Son(School,Father):
    def __init__(self):
        self.recipe = "独创面条配方"
    def make_noodles(self):
        self.__init__()
        print("使用"+self.recipe+"制作面条")
    def make_father_noodles(self):
        super(School,self).__init__()
        super(School,self).make_noodles()
    def make_school_noodles(self):
        super().__init__()
        super().make_noodles()

# 使用子类创建一个对象,并调用父类方法和属性
jachin = Son()
print(jachin.recipe)
jachin.make_father_noodles()
jachin.make_school_noodles()

# 输出
独创面条配方
使用祖传面条配方制作面条
使用通用面条配方制作面条
多层继承

多层继承就是子类的子类可以继承祖先的属性和方法。

# 模拟一家餐馆,爷爷创立门派。
# 父亲,孙子都继承了爷爷的能力。
class Grandfather(object):
    def __init__(self):
        self.recipe = "祖传面条配方"
    def make_noodles(self):
        print("使用"+self.recipe+"制作面条")
class Fahter(Grandfather):
    pass
class Son(Fahter):
    pass
# 利用Son创建一个对象
jachin = Son()
jachin.make_noodles()
# 输出
使用祖传面条配方制作面条
私有属性和私有方法
定义私有属性和私有方法

Python中,设置私有属性和私有方法,可让父类有些属性和方法可以不继承给子类。

设置私有权限的方法:在属性名和方法名前加上两个下划线__

class Grandfather(object):
    def __init__(self):
        self.recipe = "祖传面条配方"
        self.__private_assets = "200000000RMb"
    def __private_noodle(self):
        print("不可传")
    def make_noodles(self):
        print("使用"+self.recipe+"制作面条")
class Fahter(Grandfather):
    pass
# 利用Son创建一个对象
jachin = Fahter()
print(jachin.__private_assets)

# 输出
发生异常:
'Fahter' object has no attribute '__private_assets'

jachin.__private_noodle()
# 输出
发生异常:
'Fahter' object has no attribute '__private_noodle'

私有属性和私有方法只能在类里面访问和修改。

获取和修改私有属性值

在Python中,习惯使用定义方法名get_xx用来获取私有属性,定义set__xx用来修改私有属性。

class Grandfather(object):
    def __init__(self):
        self.recipe = "祖传面条配方"
        self.__private_assets = "200000000RMb"
    def get_private_assets(self):
        return self.__private_assets
    def set_private_assets(self,money):
        self.__private_assets = money
    
    def __private_noodle(self):
        print("不可传")

    def make_private_noodle(self):
        print("我现在偷偷给你说")
        self.__private_noodle()
    
    def make_noodles(self):
        print("使用"+self.recipe+"制作面条")
class Father(Grandfather):
    pass
# 利用Father创建一个对象
jachin = Father()
jachin.set_private_assets("30RMB")
print(jachin.get_private_assets())
jachin.make_private_noodle()
# 输出
30RMB
我现在偷偷给你说
不可传
多态
多态

多态指的是一类事物有多种形态。

多态是一种使用对象的方式,子类重写父类方法,调用不同子类对象的相同父类方法,可以产生不同的执行结果

使用方法
class Animal(object):
    def calls(self):
        pass
class Dog(Animal):
    def calls(self):
        print("bark")
class Bee(Animal):
    def calls(self):
        print("buzz")
class Bird(Animal):
    def calls(self):
        print("tweet")
class Person(object):
    def play_with_animal(self,animal):
        animal.calls()
huahua = Dog()
jiji = Bee()
tutu = Bird()
jachin = Person()
jachin.play_with_animal(huahua)
jachin.play_with_animal(jiji)
jachin.play_with_animal(tutu)

# 输出
bark
buzz
tweet
类属性和实例属性
类属性
设置类属性

类属性就是类对象 所拥有的属性,它被该类的所有实例对象所共有。

类属性可以使用类对象实例对象访问。

因此,当需要记录某项数据需要保存一致时,则定义类属性。

实例属性要求每个对象为其开辟一份独立的内存空间来记录数据,但类属性为全类所共有,改一份,全类都会被改。

class Dog(object):
    feet = 4

xiaotianquan = Dog()
xiaomei = Dog()

print(Dog.feet)
print(xiaotianquan.feet)
print(xiaomei.feet)
# 输出
4
4
4
修改类属性

类属性只能通过类对象修改,不能通过实例对象修改,如果通过实例对象修改类属性, 表示的是为该实例对象创建了一个实例属性。

class Dog(object):
    feet = 4

xiaotianquan = Dog()
xiaomei = Dog()


# 修改类属性
Dog.feet = 2
print(Dog.feet)
print(xiaotianquan.feet)
print(xiaomei.feet)

# 用实例对象修改
xiaotianquan.feet = 3
print(Dog.feet)
print(xiaotianquan.feet)
print(xiaomei.feet)

# 输出
2
2
2
2
3
2
实例属性

实例属性就是通常通过__init__()魔法方法创建的属性,它不能通过类访问。

类方法和静态方法
类方法
类方法特点

需要使用装饰器@classmethod来标识其为类方法,对于类方法,第一个参数必须是类对象,一般以cls作为第一个参数。

使用场景

当方法中需要使用类对象,比如访问私有类属性时,定义类方法。

类方法一般和类属性配合使用。

class Dog(object):
    __feet = 4
    @classmethod
    def get_feet(cls):
        return cls.__feet
xiaotianquan = Dog()
print(xiaotianquan.get_feet())
# 输出
4
静态方法
静态方法特点
  • 需要通过装饰器@staticmethod来进行修饰,静态方法既不需要传递类对象也不需要传递实例对象(形参没有self/cls)
  • 静态方法 也能够通过 实例对象类对象 去访问。
使用场景
  • 当方法中 既不需要使用实例对象(如实例对象,实例属性),也不需要使用类对象 (如类属性、类方法、创建实例等)时,定义静态方法
  • 取消不需要的参数传递,有利于 减少不必要的内存占用和性能消耗
class Dog(object):
    @staticmethod
    def info_print():
        print('这是一个狗类,用于创建狗实例....')
wangcai = Dog()
# 静态方法既可以使用对象访问又可以使用类访问
wangcai.info_print()
Dog.info_print()
# 输出
这是一个狗类,用于创建狗实例....
这是一个狗类,用于创建狗实例....
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值