目录
1.1.3面向对象编程 (OOP-Object Oriented Programming)
1. 什么是面向对象
1.1 常见三种编程范式
1.1.1 函数式编程
•
函数可以作为参数传递、修改,或作为返回值
•
函数内不修改外部变量的状态
1.1.2面向过程编程 (函数)
•
根据操作数据的语句块来实现功能。
1.1.3面向对象编程 (OOP-Object Oriented Programming)
•
把数据和功能结合起来,用称为对象的东西包裹起来组织程序的方法。
###################################
1.2 面向过程和面向对象
面向过程是一件事该怎么做,着重于
做什么
面向对象是一件事该让谁来做,着重于
谁去做
###################################
1.3 面向对象的基本概念
对象:通过类定义的数据结构实例,
对象包括两个数据成员(类变量和实例变量) 和方法
python一切皆对象,类是对象,实例也是对象
类:
类(class):用来描述具有相同属性和方法的对象的集合
它定义了该集合中每个对象所共有的属性和方法,对象是类的实例
例:
class ATM():
# 属性
money = 50000
country = "china"
bank = "gonghang"
# 方法
def get_money(self, money):
print(f'get money:{money}')
实例:
具体的某个事物,实实在在的例子
实例化:创建一个类的实例,类的具体对象
# 实例化:创建一个类的实例
# a1,a2 就是实例
a1 = ATM()
a2 = ATM()
print(dir(a1))
print(a1.money, a2.country)
a1.get_money(500)
E:\python\python3.9.1\python.exe E:/tlbb/2022-05-28-python面向对象/01.面向对象.py
['__class__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__le__', '__lt__', '__module__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__', 'bank', 'country', 'get_money', 'money']
50000 china
get money:500
Process finished with exit code 0
###################################
1.4 类的基本特点
• 封装(Encapsulation)
•
在类中对数据的赋值、内部调用对外部用户是透明的。
•
把一些功能的实现细节不对外暴露
• 继承(Inheritance)
•
继承:即一个派生类(derived class)继承基类(base class)的字段和方法。
•
为实现代码的重用,
一个类可以派生出子类
•
继承也允许把一个派生类的对象作为一个基类对象对待。
• 多态(Polymorphism)
•
接口重用
•
一个接口,多种实现(重写)
###################################
2. 类的定义和使用
2.1 命名的规范
• 类名的规范
•
一般首字母大写(大驼峰)
•
Person, GoodsInfo
• 函数的命名
•
由小写字母和下划线组成
•
scan_book, drink
###################################
2.2 类的定义
类的定义方式(关键字:class)
python2 --》经典类和新式类
python3 --》新式类
###################################
2.2.1 定义最简单的类:
class A:
pass
class B():
pass
class C(object):
pass
###################################
2.2.2 python2和python3关于新式类的区别
python2只有显示继承object才是新式类,反之就是经典类
所以 class A 和 classB 都是经典类, classC是新式类
在python3里默认都是继承object,所以都是新式类
###################################
2.2.3 实例化:创建一个类的是实例
class ATM():
# 属性
money = 50000
country = "china"
bank = "gonghang"
# 方法
def get_money(self, money):
print(f'get money:{money}')
a1,a2 就是实例
# 实例化:创建一个类的实例
# a1,a2 就是实例
a1 = ATM()
a2 = ATM()
print(dir(a1))
# 属性访问
print("实例访问".center(20, '*'))
print(a1.money, a2.country)
a1.get_money(500)
print("类访问".center(20, '*'))
print(ATM.money)
print('='*30)
E:\python\python3.9.1\python.exe E:/tlbb/2022-05-28-python面向对象/02.类的定义和使用.py
['__class__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__le__', '__lt__', '__module__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__', 'bank', 'country', 'get_money', 'money']
********实例访问********
50000 china
get money:500
********类访问*********
50000
==============================
给a1添加属性,只有a1有这个属性,a2没有,ATM也没有,所以执行print会报错
# 给a1添加属性,只有a1有这个属性,a2没有,ATM也没有
a1.area = "hunan"
print(a1.area, a2.area)
Traceback (most recent call last):
File "E:\tlbb\2022-05-28-python面向对象\02.类的定义和使用.py", line 52, in <module>
print(a1.area, a2.area)
AttributeError: 'ATM' object has no attribute 'area'
给ATM类添加属性,a1,a2实例都会有这个属性
# 给ATM类添加属性
ATM.color = "blue"
print(a1.color, a2.color)
blue blue
###################################
2.3 类空间和实例空间
类空间和实例空间相互独立,但是实例空间可以访问类空间
class ATM():
# 属性
money = 50000
country = "china"
bank = "gonghang"
# 方法
def get_money(self, money):
print(f'get money:{money}')
# 类空间和实例空间相互独立,但是实例空间可以访问类空间
print("类空间".center(30, '*'))
print(ATM.__dict__)
print("a1的空间".center(30, '*'))
print(a1.__dict__)
print("a2的空间".center(30, '*'))
print(a2.__dict__)
*************类空间**************
{'__module__': '__main__', 'money': 50000, 'country': 'china', 'bank': 'gonghang', 'get_money': <function ATM.get_money at 0x000001E9A3C76AF0>, '__dict__': <attribute '__dict__' of 'ATM' objects>, '__weakref__': <attribute '__weakref__' of 'ATM' objects>, '__doc__': None, 'color': 'blue'}
************a1的空间*************
{'area': 'hunan'}
************a2的空间*************
{}
指针可以访问类空间,但是不能修改类空间
# 指针可以访问类空间,但是不能修改类空间
a1.money = 20000
print(a1.money, a2.money)
20000 50000
类创建的时候会生产类空间 实例化对象生产实例空间,不同的实例空间,空间都是独立的 实例查找属性方法的时候,先在实例空间查找,找不到就去类空间查找 类空间找不到,就去父类空间找 实例空间会有一个类对象指针,通过这个指针实例就可以访问类的属性方法了
###################################
2.4 __init__实例初始化
•
这个名称的开始和结尾都是双下划线。
•
这个方法可以用来对你的对象做一些你希望的
初始化
任务。
•
__init__()方法是一种特殊的方法,被称为类的构造函数或初始化方法,
它在类的一个对象被建立后,自动运行。
###################################
2.4.1 给ATM类添加 area地域信息
class ATM():
# 类属性
money = 50000
country = "china"
bank = "gonghang"
# 这个area是形参
def __init__(self, area):
# 这个area是实例属性
self.area = area
# 方法
def get_money(self, money):
print(f'get money:{money}')
# 实例化
atm1 = ATM("hunan")
atm2 = ATM("hubei")
print(atm1.area, atm2.area)
E:\python\python3.9.1\python.exe E:/tlbb/2022-05-28-python面向对象/02.类的定义和使用.py
hunan hubei
Process finished with exit code 0
###################################
2.5 __new__方法
•
这个名称的开始和结尾都是双下划线。
•
这个方法用来创建一个实例,一般情况下都不会重写。
class ATM():
# 类属性
money = 50000
country = "china"
bank = "gonghang"
# 这个area是形参
def __init__(self, area):
# 这个area是实例属性
print("this is init>>>>>")
self.area = area
def __new__(cls, *args, **kwargs):
print("this is new method:", cls)
print(args, kwargs)
# cls 代表当前类
return object.__new__(A)
# 方法
def get_money(self, money):
print(f'get money:{money}')
atm1 = ATM("changsha")
# 这里因为 __new__没有
atm1.get_money(500)
print(atm1)
###################################
2.5.1 总结
__new__ 是创建实例的方法
__init__是创建好的实例进行初始化的方法
__new__方法必须要传入一个参数(cls),代表当前类
__init__的self就表示__new__返回的实例, __init__再对这份实例进行初始化
子类没有定义__new__,就会去找父类的__new__
新式类才有__new__
如果实例化对象和本身class不一致, __init__不会执行
__new__方法属于静态方法
__init__方法是实例方法
###################################
2.6 单例模式
无论实例化多少次,都返回同一个对象实例
# 单例模式
# 无论实例化多少次,都返回同一个对象实例
# __new__
# 实例空间从class开始就已经存在,
class Danli:
instance = None
def __new__(cls, *args, **kwargs):
if cls.instance is None:
cls.instance = object.__new__(cls)
return cls.instance
# 创建一个实例空间
d1 = Danli()
d2 = Danli()
print(id(d1), id(d2))
E:\python\python3.9.1\python.exe E:/tlbb/2022-05-28-python面向对象/02.类的定义和使用.py
2309763436448 2309763436448
Process finished with exit code 0
3.0 self详解
self代表当前的对象,而不是类
class User():
name = "sc"
def info(self):
print(f"i am {self.name}")
print(self)
print(self.__class__)
user1 = User()
user1.info()
user2 = User()
user2.info()
E:\python\python3.9.1\python.exe E:/tlbb/2022-05-28-python面向对象/03.self详解.py
i am sc
<__main__.User object at 0x00000263B7210FD0>
<class '__main__.User'>
i am sc
<__main__.User object at 0x00000263B7210FA0>
<class '__main__.User'>
Process finished with exit code 0
###################################
3.1 self不必非写成self
只是一般约定俗成使用self
class User():
name = "sc"
def info(this):
print(f"i am {this.name}")
print(this)
print(this.__class__)
user1 = User()
user1.info()
E:\python\python3.9.1\python.exe E:/tlbb/2022-05-28-python面向对象/03.self详解.py
i am sc
<__main__.User object at 0x000001DF0F44FE80>
<class '__main__.User'>
Process finished with exit code 0
###################################
3.2 self可以不写
但是不写self的话,无法使用实例进行调用,
因为实例调用的时候会自动将实例作为一个参数传进去
# self 可以不写
# 但是不可以使用实例进行调用,因为实例调用会自动将实例作为一个参数穿进去
class User():
name = "sc"
def info(this):
print(f"i am {this.name}")
print(this)
print(this.__class__)
def info2():
print("this is info2")
user1 = User()
user1.info() # ---->User.info(user1)
user1.info2() # --->user.info2(user1)
user2 = User()
user2.info() # --->User.info(user2)
E:\python\python3.9.1\python.exe E:/tlbb/2022-05-28-python面向对象/03.self详解.py
Traceback (most recent call last):
File "E:\tlbb\2022-05-28-python面向对象\03.self详解.py", line 53, in <module>
user1.info2() # --->user.info2(user1)
TypeError: info2() takes 0 positional arguments but 1 was given
i am sc
<__main__.User object at 0x0000021C0AFD0FD0>
<class '__main__.User'>
Process finished with exit code 1
###################################
3.3 例题
# 用户名 # 属性 名字, 密码,余额 # 行为 # 购物 --》余额减少 商品库存减少 # 商品类 # 属性 类别, 名字, 单价, 库存(斤)
示例1:
实现了基本功能,但是没有体现面向对象 谁去做的思想
不应该把公共属性写死,最好使用__init__对实例进行初始化
class User():
goods_name = 'apple'
goods_price = 5
goods_num = 500
def __init__(self, name, pd):
if name == 'wang' and pd == '123456':
print("sucessfully login".center(30, '*'))
print(f"今日商品: {self.goods_name}")
print(f"商品单价: {self.goods_price}")
print(f"商品数量: {self.goods_num}")
self.flag = 1
self.money = 500
else:
print("error to login")
def buy_goods(self, goodname, goodcount):
if self.flag == 1:
self.goods_num -= goodcount
print(f"当前实时库存:{self.goods_num}")
self.money = self.money - goodcount * self.goods_price
print(f"您当前余额:{self.money}")
user1 = User('wang', '123456')
user1.buy_goods('apple', 1)
******sucessfully login*******
今日商品: apple
商品单价: 5
商品数量: 500
当前实时库存:499
您当前余额:495
Process finished with exit code 0
###################################
示例2:
面向对象的思想最重要的是谁去做,而不是怎么做!
class User:
def __init__(self, name, passwd, money):
self.name = name
self.passwd = passwd
self.money = money
def buy_goods(self, good, weight):
if weight > good.store:
print("库存不足!")
else:
pay = weight * good.price
if self.money >= pay:
self.money -= pay
good.store -= weight
print(f"购买成功,{self.name}剩余{self.money}元,"
f"{good.product_name},剩余库存{good.store}斤")
else:
print("余额不足!")
class Goods:
def __init__(self, classify, product_name, price, store):
self.classify = classify
self.product_name = product_name
self.price = price
self.store = store
user1 = User("zhangj", "123456", 5000)
user2 = User("wangsh", "1234567", 8000)
apple = Goods("fruits", "apple", 8, 30)
orange = Goods("fruits", "orange", 4, 100)
user1.buy_goods(apple, 3)
E:\python\python3.9.1\python.exe E:/tlbb/2022-05-28-python面向对象/03.self详解.py
购买成功,zhangj剩余4976元,apple,剩余库存27斤
Process finished with exit code 0