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 6, in <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 7, in <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("微信", 100, 20)
print("------传入下单类------")
useIsinstance(p)
print("------传入退货类------")
# 实例化-退货类
r = order.RefundGoods()
useIsinstance(r)

# ---------------- 输出 ----------------

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