面向对象的由来
ps : 一个软件质量因素有很多: 性能, 可维护, 可扩展, 可移植, 成本, 安全…, 而面向对象解决的仅仅是可扩展性的问题, 所以它也是有局限性的
⛅在没有学习类这个概念时,数据与功能是分离的
⛅每次调用都需要重复传入一堆参数, 我们能想到的解决方法是,把这些变量都定义成全局变量
⛅这样我们将会定义一大堆全局变量,这些全局变量并没有做任何区分,即能够被所有功能使用
⛅然而事实上只有某一些对象才使用某一些它们所需要的功能, 并不是全部的功能都需要
⛅言外之意:我们必须找出一种能够将数据与操作数据的方法组合到一起的解决方法,这就是我们说的类了
⛅"现实世界中 : 先有对象, 再有类
世界上现实有了各种各样的物种:猪,狗,猫,人,然后我们将其归为:猪类,犬类,猫类,人类
⛅"在程序中 : 先有类, 再有对象
与函数类似, 先定义再调用, 类也是一样, 先定义类, 再调用类
不同的是函数调用时执行函数体代码, 而类则是实例出一个对
制造一个"鸭子对象",鸭子有不同品种"特征", 鸭子会叫, 还会跑这些"技能" (特征与对象的结合体: 就是属性与方法)
⛅先定义一个"鸭子类"
class Duck:
⛅特征(属性)
bread = "你好鸭"
color = "yello"
⛅技能(方法),特殊的函数,自带"self"
def run(self):
print("技能奔跑")
⛅定义一个"鸭子对象"
duck1 = Duck()
⛅使用对象
print(duck1.bread) # 你好鸭
print(duck1.color) # yello
duck1.run() # 技能奔跑
__dict__
: 类的属性字典[类名].__dict__
来进行查看储存的属性字典, 其键为属性名,值为属性的值.__dict__
来查看"."(点)专门用来访问属性, 本质上就是在操作"__dict__"
print(Duck.__dict__)
'''输出结果
{'__module__': '__main__', 'bread': '你好鸭', 'color': 'yello',\
'run': , '__dict__': ,\
'__weakref__': , '__doc__': None}
''' “__”开头的可以先不要关注
Duck.bread # 等于经典类的操作 : Duck.__dict__["bread"]
Duck.color = "black" # 等于经典类的操作 : Duck.__dict__["color"] = "black"
Duck.new_x = "haha" # 等于经典类的操作 : Duck.__dict__["new_x"] = "haha"
del Duck.new_x # 等于经典类的操作 : Duck.__dict__.pop("new_x")
class Duck:
bread = "你好鸭"
color = "yello"
"self"
def run(self):
print("技能奔跑")
duck1 = Duck()
duck1.name = "哎鸭" # 定制独有的品种
duck1.color = "black" # 定制独有的颜色
duck1.weight = 20 # 定制独有的重量
print(duck1.name) # 哎鸭
print(duck1.color) # black
print(duck1.weight) # 20
__init__
方法上面我们介绍了一种给对象定制独有特征的方法,下面我们使用"__init__"方法直接进行初始化赋值
⛅新方案, 只要是类实例化得到对象, 就会自动触发"__init__"的执行
class Duck:
def __init__(self):
self.bread = "你好鸭"
self.color = "yello"
def run(self):
print(f"{self.bread}有技能奔跑")
duck1 = Duck()
print(duck1.bread) # 你好鸭
print(duck1.color) # yello
duck1.run() # 你好鸭有技能奔跑
⛅"__init__"的升级使用, 触发"__init__"的执行, 并传入参数(传参原则与函数传参相同)
class Duck:
def __init__(self,bread,color):
self.bread = bread
self.color = color
def run(self):
print(f"{self.bread}有技能奔跑")
duck1 = Duck("快跑鸭","black")
duck2 = Duck("可以鸭","blue")
duck3 = Duck("牛鸭","white")
print(duck1.bread) # 快跑鸭
print(duck1.color) # black
duck1.run() # 快跑鸭有技能奔跑
print(duck2.bread) # 可以鸭
print(duck2.color) # blue
duck2.run() # 可以鸭有技能奔跑
print(duck3.bread) # 牛鸭
print(duck3.color) # white
duck3.run() # 牛鸭有技能奔跑
ps : id是python的实现机制,并不能真实反映内存地址,如果有内存地址,还是以内存地址为准
class Duck:
master = "shawn"
def __init__(self,bread,size):
self.bread = bread
self.size = size
duck1 = Duck("嘿鸭",100)
duck2 = Duck("好的鸭",80)
print(id(duck1.master)) # 1905145581488
print(id(duck2.master)) # 1905145581488
class Duck:
master = "shawn"
def __init__(self,bread,size):
self.bread = bread
self.size = size
def run(self):
print(f"{self.bread}在跑")
duck1 = Duck("嘿鸭",100)
duck2 = Duck("好的鸭",80)
duck3 = Duck("别鸭",80)
print(Duck.run) #
print(duck1.run) # >
print(duck2.run) # >
print(duck3.run) # >
⛅对象更改属性, 改的只是自己的
class Duck:
master = "shawn"
def __init__(self,bread,size):
self.bread = bread
self.size = size
def run(self):
print(f"{self.bread}在跑")
duck1 = Duck("不要鸭",80)
duck1.master = "song" # 更改属性
print(Duck.master) # shawn
print(duck1.master) # song
⛅类修改
class Duck:
master = "shawn"
def __init__(self,bread,size):
self.bread = bread
self.size = size
def run(self):
print(f"{self.bread}在跑")
duck1 = Duck("酱紫鸭",80)
Duck.master = "xing" # 类修改属性
print(Duck.master) # xing
print(duck1.master) # xing
ps : self 可以是任意名字,但是约定俗成地写成 self
__init__
是一样的道理class Duck:
master = "shawn"
def __init__(self,bread,size):
self.bread = bread
self.size = size
def run(self):
print(f"{self.bread}在跑")
def eat(self):
print(f"{self.bread}在吃东西")
def sleep(self):
print(f"{self.bread}在睡觉")
duck1 = Duck("可恶鸭",80)
duck2 = Duck("厉害鸭",50)
duck3 = Duck("好惨鸭",90)
duck1.run() # 可恶鸭在跑
duck2.eat() # 厉害鸭在吃东西
duck3.sleep() # 好惨鸭在睡觉
Duck.run(duck1) # 可恶鸭在跑
Duck.eat(duck2) # 厉害鸭在吃东西
Duck.sleep(duck3) # 好惨鸭在睡觉
list1 = list([1,2,3])
dict1 = dict({
"name":"shawn"})
int1 = int("12311321")
float1 = float("11.3")
tuple1 = tuple((1,2,3))
set1 = set(list1)
bool1 = True
print(type(list1)) #
print(type(dict1)) #
print(type(int1)) #
print(type(float1)) #
print(type(tuple1)) #
print(type(set1)) #
print(type(bool1)) #
⛅使用"list"类实例化出一个对象
list1 = list([1,2,3,4])
list2 = list([5,6,6,8])
⛅每个对象都可以使用"list"类的公共属性和方法,我们称之为绑定方法,并且绑定给不同的对象, 内存地址也不相同
print(list1.append) #
print(list2.append) #
⛅实例化出来的每个对象都是相互独立的个体, 相互不影响
list1.append(1)
list2.insert(0,9)
print(list1) # [1, 2, 3, 4, 1]
print(list2) # [9, 5, 6, 6, 8]
在上述介绍类与对象的使用过程中,我们更多的是站在底层原理的角度去介绍类与对象之间的关联关系
如果只是站在使用的角度,我们无需考虑语法“对象.属性"中”属性“到底源自于哪里,只需要知道是通过对象获取到的就可以了
所以说,对象是一个高度整合的产物,有了对象,我们只需要使用”对象.xxx“的语法就可以得到跟这个对象相关的所有数据与功能,十分方便且解耦合程度极高