python面向对象
1.类
1.1引入类
面向对象:
所谓面向对象,就是在编程的时候尽可能的去模拟真实的现实世界,按照现实世界中的逻辑去处理问题,分析问题中参与其中的有哪些实体,这些实体应该有什么属性和方法。我们如何通过调用这些实体中的属性和方法去解决问题
类:用来描述具有相同的属性和方法的对象的集合。它定义了集合中每一个对象所共有的熟悉和方法,对象是类的实例
使用class创建类
类没有创建作用域(所以不需要申明作用域)
类创建命名空间(将同名的变量隔离了)
命名:
变量名的风格:没有大写字母,单词之间,使用下划线分隔
类名风格:单词首字母大写,不使用下划线
优势:
- 不使用闭包,减少内存泄漏风险
- 不使用闭包,实现业务直接变量隔离
- 使用类,可以从外部访问内部变量
- 使用类,不会因为重复执行代码,导致数据被销毁
class a: #创建类,没有创建作用域
n=0 #统计次数
def f():
print(f"{a.n=}")
a.n+=1
class b:
n=""
def g():
print(f"{b.n=}")
b.n+="s"
n="zhangsan"
a.f()
b.g()
a.f()
b.g()
a.f()
b.g()
1.2 创建类
要素:
名字
属性(变量)
方法(函数
class hourse:
name=""
area=0 #面积
room_count=0 #房子数量
price=0 #单价
def amount(self):
return self.m2*self.prices
1.3 使用类
类是为了解决实际问题
面向对象是为了解决设计问题
1.4.对象
对象是按照类,生成的多个相互隔离的空间
__init__:双下线特殊函数,在特殊的时机,由python自动调用
- 在类实例化时,自动调用
- 接收实例化参数
- 第一个位置参数,是实例对象本身(self)
- 不应该有返回值
class hourse:
name=""
area=0 #面积
room_count=0 #房子数量
price=0 #单价
def __init__(self,a,b,c,d): #双下线特色函数:在特殊的时机,由python自动调用
print(self,a,b,c,d)
c1=hourse(3,4,5,6) #创建对象
c2=hourse(7,8,9,0)
c3=hourse(1,2,3,4)
1.5.属性
概念:和变量类似,用于存储数据,可以访问
类属性:类属性在整个实例化的对象中是公用的。类属性定义在类中且在函数体之外。类属性通常不作为实例属性使用
如何修改类属性:
- 类.属性=xxx
- self.__class__.属性=xxx
- cls.属性=XXX
如何修改实例属性
- 实例.属性=xxx
- self.属性=XXX
class a: #创建类,没有创建作用域
n=0 #类属性:统计次数
def f(self):
self.b="a" #实例属性
print(f"{a.n=}")
a.n+=1
说明:如果实例有属性,则使用自己的属性,没有属性则使用类属性
1.6 方法
概念:类中定义的函数。类的方法与普通的函数只有一个特别的区别——它们必须有一个额外的第一个参数名称,按照惯例她的名称是self(其实取什么名字不重要,只是有这个参数就行,默认系统叫做self)
定义在类中的函数,称之为方法,因为会自动传递参数
如果某方法,不接受参数,直接访问结果(以固定的方式返回数据)
可以通过装饰器,伪装成属性,可以不加括号直接读取
class hourse:
name=""
area=0 #面积
room_count=0 #房子数量
price=0 #单价
def __init__(self,a,b,c,d): #双下线特色函数:在特色的时机,由python自动调用
print(self,a,b,c,d)
@property #可以通过装饰器,伪装成属性
def amount(self):
return self.area*self.price
print(c2.amount) #可以不加括号直接读取
1.6.1 类方法
传递类本身
class a:
@classmethod #此装饰器修饰的方法称为类方法
def b(cls):
pass
1.6.2 实例方法
传递实例对象
class a:
def b(self): #实例方法
pass
1.6.3 静态方法
什么都不传递
class a:
@staticmethod
def b():
pass
他们的区别:就是是否会自动传递参数,以及传递的值是什么
如果需要接收额外的参数,可以自由的定义
1.7 面向对象三大特征
1.7.1 封装
封装:对数据进行封装,防止被外部意外的修改或者破坏
Python约定:
- 下划线开头的(属性和方法),仅供类内部使用
- 双下线开头的(属性和方法),仅供本类使用
约定没有强制约束力,可以绕过
- b._age=-100 #age属性:可以绕过
- b._A__age=-100 #age属性:可以绕过
class A:
name=""
_age=0
__sex='男'
@property
def age(self):
return self._age
@age.setter
def age(self,value):
assert value>0
self._age=value
def say(self):
print(f"I am {self.name},{self._age} year old")
a=A()
a.age=1 #age属性:可读不可写
print(a.age)
print(a.say())
class B(A):
def b_say(self):
print(f"I am {self.name},{self._age} years old")
b=B()
b.age=3
b._age=-100 #age属性:可以绕过
b._A__age=-100 #age属性:可以绕过
print(b.age)
1.7.2 继承
首先,继承实现了代码的复制
其次,继承创建了关系:子类的实例,也被认为是父类的实例
class A:
name=""
_age=0
__sex='男'
@property
def age(self):
return self._age
@age.setter
def age(self,value):
assert value>0
self._age=value
def say(self):
print(f"I am {self.name},{self._age} year old")
a=A()
a.age=1 #age属性:可读不可写
print(a.age)
print(a.say())
class B(A):
def b_say(self):
print(f"I am {self.name},{self._age} years old")
b=B()
b.age=3
print(b.age)
print("b是B的实例对象",isinstance(b,B))
print("b是A的实例对象",isinstance(b,A))
1.7.3 多态
B并非一定是A的子类,但是如果B在用起来和A没有区别,那么B也可以代替A出席需要A的场合
任意一个类型,都可以代替目标类型出现
在使用的时候,数据能够按照期望的方式使用,就可以了
class A:
name=""
_age=0
__sex='男'
@property
def age(self):
return self._age
@age.setter
def age(self,value):
assert value>0
self._age=value
def say(self):
print(f"I am {self.name},{self._age} year old")
class B(A):
def b_say(self):
print(f"I am {self.name},{self._age} years old")
print("b是B的实例对象",isinstance(b,B))
print("b是A的实例对象",isinstance(b,A))
def hello(obj:A): #hello 函数需要A的实例参数作为参数
obj.say() #因为要调用say方法
hello(b)
1.8 练习
#1.通过类 设计一种动物,他们应该拥有不同的名字、体重、身高,每个动物都可以计算出自己的BMI
class Animal:
name=""
weight=0
height=0
def __init__(self,name,weight,height):
self.name=name
self.weight=weight
self.height=height
def bmi(self):
"""
bmi=体重/(身高*身高 )
:return:
"""
return self.weight/(self.height*self.height)
a=Animal("金毛",200,500)
b=Animal("小喵",80,150)
#2.根据面向对象的特性,创建一个可以被say函数作为参数的Cat类,使一下代码执行正确
class Dog:
_msg="旺旺"
def say(self):
return self._msg
# class Cat(Dog): #方式1:通过继承实现
# _msg="喵喵"
class Cat:
def say(self): #方式2:通过多态实现
return "喵喵"
def say(obj):
print(obj.say())
say(Dog())
say(Cat())