Python学习(七):面向对象

Python中,一切皆是对象。

1. 快速入门

1.1 定义类

文件位置: basis/classdemo.py

# 使用关键字class声明类
class Person(object):
    def __init__(self, name, age):
        self.name = name
        self.age = age

    def say(self):
        content = "我是{},今年{}岁".format(self.name, self.age)
        print(content)
        

1.2 类代码说明

  • class Person(object): 使用关键字class创建类,Person是类名;object指的是基类;

    所有的类都可以继承自一个称为object的基类。在Python 3中,这是默认的行为,即使你没有显式地指定object作为基类,Python也会自动将其作为基类.

  • __init__: 类的构造函数;

  • self.name 和 self.age: 指的是成员变量;

  • say(self): 指的成员方法

1.3 创建对象

from basis import classdemo # 导入

if __name__ == "__main__":
    # 实例化类
    p1 = classdemo.Person("张三"18)
    # 调用类的成员方法
    p1.say()
    # 访问类的成员属性
    print("p1.name", p1.name)
    print("p1.age", p1.age)

# 我是张三,今年18岁
# p1.name 张三
# p1.age 18

1.4 代码说明

  • from basis import classdemo: 指的从模块 basis导入 classdemo这个包;
  • classdemo.Person: 基于类创建对象;
  • p1.say() : 访问成员方法
  • p1.name 和 p1.age: 访问成员属性;

2. 构造函数

Python中的构造函数使用特殊的方法名__init__来定义,它位于类的内部。当创建一个类的实例时,会自动调用该类的构造函数,并传递必要的参数。

格式: def __init__(self, *args)

@注意:当__init__定义几个参数,实例化时,就需要传几个参数,除非原参数有默认值,否则会报错

2.1 没有默认值

# 类的定义
class Person(object):
    # 构造函数参数没有默认值
    def __init__(self, name, age):
        self.name = name
        self.age = age
   ...
# 实例化
p1 = Person()

#### ------ 报错如下:  ------ ####
Traceback (most recent call last):
  File "/Users/liuqh/ProjectItem/PythonItem/python-learn-demo/main.py", line 6in <module>
    p1 = classdemo.Person()
         ^^^^^^^^^^^^^^^^^^
TypeError: Person.__init__() missing 2 required positional arguments: 'name' and 'age'

2.2 有默认值

# 类的定义
class Person(object):
   # 构造函数参数没有默认值
    def __init__(self,  name="张三", age=19):
        self.name = name
        self.age = age
   ...
# 实例化
p1 = Person()
# 访问类的成员属性
print("p1.name", p1.name)
print("p1.age", p1.age)

# ----------- 输出:  ----------- #
# p1.name 张三
# p1.age 19

3. 访问权限

3.1 公有属性

有时为了确保类内的属性的安全,我们是不希望外部直接访问或者修改类的属性信息;如下面简单示例:

# ---------------- 类文件:basis/bank.py ----------------
# 定义类
class Bank:
    def __init__(self, amount):
        self.amount = amount

    # 花钱
    def use_money(self, useAmount):
        self.amount = self.amount - useAmount
        print("花掉:{},剩余金额:{}".format(useAmount, self.amount))
        
# ----实例化类 ------
from basis import bank

if __name__ == "__main__":
    # 实例化类,充值100元
    b = bank.Bank(100)
    # 花掉10元
    b.use_money(10)
    # 在外部改余额
    b.amount = 10
    # 在花10元
    b.use_money(10)
    
# --- 输出 ---
# 花掉:10,剩余金额:90
# 花掉:10,剩余金额:0

上面示例演示充值100,花了两次10元,因为外部可以直接修改类属性,最后发现余额变成0元;

3.2 私有属性

Python中没有关键字public(代表公有)、private(代表私有),如果想定义私有属性,直接在属性名称前面增加__(2个底线),就变成了私有属性; 修改上面示例:

# ---------------- 类文件:basis/bank.py ----------------
# 定义类
class Bank:
    def __init__(self, amount):
        self.__amount = amount

    # 花钱
    def use_money(self, useAmount):
        self.__amount = self.__amount - useAmount
        print("花掉:{},剩余金额:{}".format(useAmount, self.__amount))
        
# ---------------- 实例化类  ----------------
from basis import bank

if __name__ == "__main__":
    # 实例化类
    b = bank.Bank(100)
    # 花掉10元
    b.use_money(10)
    # 在外部尝试修改私有属性
    b.__amount = 10
    # 在花10元
    b.use_money(10)
    
# ---- 输出 ----
# 花掉:10,剩余金额:90
# 花掉:10,剩余金额:80

从上面示例可以看出,虽然在外边修改私有属性,但是从输出结果可以看出:修改并未生效

3.3 私有方法

python中默认方法都是可以直接在外边访问,如果想定义私有方法,也是直接在方法名称前面增加__(2个底线),就变成了私有方法; 如下面示例:

# ---------------- 类文件:basis/bank.py ----------------
class Bank:
    def __init__(self, amount):
        self.__amount__ = amount

    # 私有方法
    def __add_money(self, amount):
        self.__amount__ += amount
        
# ---------------- 实例化对象 ----------------
from basis import bank

if __name__ == "__main__":
    # 实例化类
    b = bank.Bank(100)
    # 私自加钱10元
    b.__add_money(10000)
    
# ---- 输出 ---- 
Traceback (most recent call last):
  File "/Users/liuqh/ProjectItem/PythonItem/python-learn-demo/main.py", line 7in <module>
    b.__add_money(10000)
    ^^^^^^^^^^^^^
AttributeError: 'Bank' object has no attribute '__add_money'. Did you mean: '_Bank__add_money'?

@注意:强制访问私有方法会直接报错。

4. 继承

Python属于面向对象的编程语言,面向对象中的继承,可以直接让我们复用父类的一些方法;

4.1 单继承

# ---------------- 类文件:basis/people.py ----------------
# 定义父类
class People:
    def __init__(self, name, age):
        self.name = name
        self.age = age

    def say(self):
        print("姓名:{} 年龄:{}".format(self.name, self.age))


# 定义男孩类
class Body(People):
    def say(self):
        print("我叫{},今年{}岁,是个帅气的男孩".format(self.name, self.age))


# 定义女孩类
class Girl(People):
    # 什么也没有
    pass

        
# ---------------- 实例化对象 ----------------        
from basis import people

if __name__ == "__main__":
    # 实例化男孩类
    body = people.Body("王麻子"38)
    girl = people.Girl("张小丽"18)
    # 调用方法
    body.say()
    girl.say()
    
# ---------------- 输出 ----------------
# 我叫王麻子,今年38岁,是个帅气的男孩
# 姓名:张小丽 年龄:18

从上面示例可以看出,继承父类后,可以直接复用父类中公有的属性(name、age)和方法(say() )。也可以在自己类中覆盖父类的方法,如Body类重新实现say()方法。

4.2 多继承

Python和其他语言对比,特殊的一点是,Python中的类支持多继承;多继承一般都会让人有个疑问: 如果同时继承多个父类,并且都存在一样的方法名,子类会调用哪个父类的方法呢?`

# ---------------- 类文件:basis/people.py ----------------
# 定义父类
class People:
    def __init__(self, name, age):
        self.name = name
        self.age = age

# 定义男孩类
class Body(People):
    def say(self):
        print("我叫{},今年{}岁,是个帅气的男孩".format(self.name, self.age))

# 定义女孩类
class Girl(People):
    def say(self):
        print("我叫{},今年{}岁,是个漂亮的女孩".format(self.name, self.age))

# 定个程序类,同时继承男孩、女孩类
class Programmer(Body, Girl):
    pass
  
# ---------------- 实例化对象 ----------------     
from basis import people

if __name__ == "__main__":
    # 实例化男孩类
    it = people.Programmer("张飞"88)
    # 调用方法
    it.say()
    
# ---------------- 输出 ----------------
# 我叫张飞,今年88岁,是个帅气的男孩

@注:如果同时继承多个父类,并且存在一样的方法名,子类会按照按继承的顺序执行对应的父类方法.

4.3 super()

在有些场景,我们不但要在子类中实现父类的方法,还需要执行父类的方法,那就可以使用super()函数来调用,如场景示例: 如我们要操作一个商品数据库,在操作之前,需要先建立连接.

# ---------------- 类文件:basis/db.py ----------------
class Database:
    def __init__(self, db_name):
        print("第一步: 和 {} 数据库建立连接".format(db_name))

class GoodsDb(Database):
    def __init__(self, db_name):
        # 在子类中调用父类方法
        super().__init__(db_name)
        print("第二步: 操作 {} 数据库".format(db_name))
        
# ---------------- 实例化对象 ----------------     
from basis import db

if __name__ == "__main__":
    # 实例化类
    it = db.GoodsDb("商品")
    
# ---------------- 输出 ----------------
# 第一步: 和 商品 数据库建立连接
# 第二步: 操作 商品 数据库       

5. 面向接口编程

Python原生是不支持抽象类和接口,有时我们想做到和其他语言一样面向接口编程时,可以通过使用关键字:isinstance:

5.1 使用语法

# 判断对象obj是否
r = isinstance(obj, cl)

5.2 使用示例

# ---------------- 类文件:basis/order.py ----------------
class Order:
    def __init__(self, accountName, totalAmount, payAmount):
        self.accountName = accountName
        self.payAmount = payAmount
        self.totalAmount = totalAmount

    # 创建订单
    def createOrder(self):
        print("支付{}元,创建订单".format(self.payAmount))

    # 扣除余额
    def deductAmount(self):
        print("扣除支付金额:{}元,余额:{}元".format(self.payAmount, self.totalAmount - self.payAmount))

# 下单
class PayGoods(Order):
    pass

# 退货
class RefundGoods:
    pass
  
# ---------------- 演示示例 ----------------  
from basis import order

def useIsinstance(cl):
    isRes = isinstance(cl, order.Order)
    if not isRes:
        print("参数不属于Pay类的对象")
        return
    # 调用方法
    cl.createOrder()
    cl.deductAmount()


if __name__ == "__main__":
    # 实例化-下单类
    p = order.PayGoods("微信"10020)
    print("------传入下单类------")
    useIsinstance(p)
    print("------传入退货类------")
    # 实例化-退货类
    r = order.RefundGoods()
    useIsinstance(r)
    
# ---------------- 输出 ----------------      

# ------传入下单类------
# 支付20元,创建订单
# 扣除支付金额:20元,余额:80元
# ------传入退货类------
# 参数不属于Pay类的对象

微信搜索【猿码记】查看更多文章

本文由 mdnice 多平台发布

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值