类是模板,对象是根据这个模板创建出来的,应该先有类,再有对象
类只有一个,但对象可以有很多个。
不同的对象之间属性可能会各不相同
类中定义了什么属性和方法,对象中就有什么属性和方法,不可能多也不可能少。
在程序开发中,要设计一个类,通常需要满足以下三个要素:
1、类名:这类事物的名字,满足大驼峰命名法(每个单词首字母大写)
2、属性:这类事物具有什么样的特征
3、方法:这类事物具有什么样的行为
特征一:封装
将属性和方法封装到一个抽象的类中,外界只需要创建类所对应的对象,由对象调用属性或方法。
class User():#定义类,()内为空默认继承object类
def __init__(self,username,password,age,address):
self.username = username
self.password = password
self.age = age
self.address = address
def eat(self,food):
print(self.username+"吃饭"+food)
def add(self,*num):
number = 0
for i in num:
number += i
return number
def __str__(self):
return "用户名:%s,密码:%s,年龄:%s,地址:%s"%(self.username,self.password,self.age,self.address)
user1 = User("张三丰","123456",100,"武当山") #定义对象
print(user1)
user1.eat("盖饭")
sum = user1.add(1,2,3,4,5)
print("sum=%s"%sum)
运行结果:
用户名:张三丰,密码:123456,年龄:100,地址:武当山
张三丰吃饭盖饭
sum=15
面向对象需要关注的特殊方法 __init__() 初始化函数 __str__() 用来输出对象详细信息 __new__() 用来开辟内存空间 __der__() 销毁对象信息 dir() 罗列可操作
#单例设计模式
class Person():
obj_instance = None
def __new__(cls,*args,**kwargs):
print("开辟内存空间")
if cls.obj_instance is None:
cls.obj_instance = super().__new__(cls)
return cls.obj_instance
def __init__(self):
print("初始化信息")
def __del__(self):
print("销毁")
person1 = Person()
person2 = Person()
person3 = Person()
person4 = Person()
print(person1)
print(person2)
print(person3)
print(person4)
运行结果:
开辟内存空间
初始化信息
开辟内存空间
初始化信息
开辟内存空间
初始化信息
开辟内存空间
初始化信息
<__main__.Person object at 0x0000021E8F93DF70>
<__main__.Person object at 0x0000021E8F93DF70>
<__main__.Person object at 0x0000021E8F93DF70>
<__main__.Person object at 0x0000021E8F93DF70>
销毁
可以看出四个对象使用同一个地址,单例模式可以节省存储空间,但是可能会出现多线程环境下的线程安全问题等。
私有属性和私有方法
私有属性:对象内部使用,不希望外界直接调用的属性
私有方法:对象内部使用,不希望外界直接调用的方法
定义方法:在定义属性或方法时,可以在属性或方法前追加双下划线__
class Person:
def __init__(self,name):
self.name = name
self.__age = 18
def __sal(self):
print("我的年龄是:%s,不要随便询问工资"%self.__age)
zhangsan = Person("张三")
print(zhangsan.name)
print(zhangsan.__age) #私有属性无法调用
zhangsan.__sal #私有方法无法调用
运行结果:
张三
报错信息:
AttributeError: 'Person' object has no attribute '__age'
AttributeError: 'Person' object has no attribute '__sal'
在python中,没有真正意义上的私有,只是通过双下划线做了特殊处理在日常生活中,不建议使用伪私有属性或伪私有方法,但是如果需要访问,可以用特殊方法暴力访问到。
访问方法:在名称前追加_类名
print(zhangsan._Person__age)
zhangsan._Person__sal()
运行结果:
18
我的年龄是:18,不要随便询问工资
特征二:继承
继承可以实现代码的重用,相同的代码不需要进行重复的编写。
子类可以使用父类的属性或方法
继承的基础使用
不使用继承时:
不使用继承
class Cat:
def eat(self):
print("吃饭")
class Dog:
def eat(self):
print("吃饭")
class Rabbit:
def eat(self):
print("吃饭")
三个类似的类有相同的行为(方法),需要写三遍相同的代码。
可以使用继承:
class Animal: #父类
def __init__(self,name,age):
self.name = name
self.age = age
def eat(self):
print(self.name+"吃饭")
class Cat(Animal):
def __init__(self,name,age,address): #子类初始化
super().__init__(name,age)
self.address = address
def catch_mouse(self):
print(self.name+"在"+self.address+"抓老鼠")
class Dog(Animal): #不写初始化默认使用父类初始化
def look_door(self):
print("看大门")
class Rabbit(Animal):
pass
tom = Cat("汤姆",3,"中北大学")
tom.eat() #使用父类方法
tom.catch_mouse()
dog = Dog("金毛",4)
dog.eat() #使用父类方法
dog.look_door()
运行结果:
汤姆吃饭
汤姆在中北大学抓老鼠
金毛吃饭
看大门
继承的传递性:
A类继承B类,B类继承C类,A拥有B类和C类两个类中的信息。
class C():
def study(self):
print("学习")
class B(C): #继承C类
pass
class A(B): #继承B类
pass
a = A()
a.study() #使用C类的方法
运行结果:
学习
方法的重写
当子类继承父类,可以直接使用父类的相关方法,但是如果需要有子类特定的相关业务逻辑,子类可以把父类的方法进行重写(方法的复写、覆盖)
class Animal():
def eat(self):
print("吃饭")
class Cat(Animal):
def eat(self): #重写父类eat方法
print("猫吃鱼")
class Mouse(Animal):
def eat(self): #重写父类eat方法
print("老鼠吃大米")
tom = Cat()
tom.eat()
jerry = Mouse()
jerry.eat()
运行结果:
猫吃鱼
老鼠吃大米
应用场景:在开发过程中,父类提供相关的方法设计,但是不同的子类拥有不同的方法的实现,在这种状况下,可以对方法进行重写。当发生方法的重写,在运行时,调用到的是重写之后的方法,而不再是父类的方法。
对父类方法的拓展:如果想使用父类的方法,可以使用super关键字。
例如修改上述Cat类为:
class Cat(Animal):
def eat(self):
super().eat() #调用父类方法
print("猫吃鱼")
那么Cat类对象调用eat方法的运行结果为:
吃饭
猫吃鱼
多继承的注意事项
当不同的父类中出现了相同的方法名称,那么子类在调用父类的方法时,根据子类继承多个父类的先后顺序来判定哪一个方法来执行。
class User:
def study(self):
print("user类学习")
class Person:
def study(self):
print("person类学习")
class Student(User,Person): #先继承的User,然后是Person
pass
zs = Student()
zs.study() #调用study方法,由于先继承的User,调用User的study方法
运行结果:
user类学习
一般在研发项目中,尽量不要出现继承的多个父类有同名方法的现象,或者避免出现多继承。
在python中提供了验证多继承顺序的模块mro,例如:
print(Student.__mro__)
运行结果:
(<class '__main__.Student'>, <class '__main__.User'>, <class '__main__.Person'>, <class 'object'>)
得到Student类优先级为Student类>User类>Pserson类>object类
新式类与旧式类
新式类:以object为基类
旧式类:不以object为基类
注意:在python3.以后,创建类如果没有继承类,那么默认继承object,都属于新式类。
继承中初始化注意事项
在子类没有提供初始化init方法的时候,初始化子类会先初始化父类init函数,若子类提供了初始化iinit方法,则默认不在父类初始化,但是在需要使用父类的一些初始化属性时会报错。
class A:
def __init__(self):
print("父类的初始化函数")
self.data = []
def addData(self,str):
self.data.append(str)
print(self.data)
def help(self):
print("通用帮助文档")
class B(A):
def __init__(self):
print("子类的初始化函数")
b = B()
b.help()
b.addData("hello")
运行结果:
子类的初始化函数
通用帮助文档
报错信息:
AttributeError: 'B' object has no attribute 'data'
原因:子类手动提供了初始化init方法,导致默认不执行父类的初始化init方法。
解决方法:建议在后续开发过程中,养成一个好习惯,当在子类中手动提供初始化init方法的时候,手动通过super方法调用父类的初始化init函数。
class B(A):
def __init__(self):
print("子类的初始化函数")
super().__init__() #手动执行父类初始化
抽象类
抽象类中设置抽象方法(方法为空),实体类继承抽象类后,规范了方法的名称和个数,继承它的实体类需要实现抽象类中的所有方法。
在项目统一开发中可以使用抽象类,来规范类的方法命名和书写,以免造成混乱。
from abc import abstractmethod,ABCMeta
class UserDao(metaclass=ABCMeta): #创建抽象类
@abstractmethod #抽象方法
def addUser(self):
pass
@abstractmethod #抽象方法
def deletUser(self):
pass
@abstractmethod #抽象方法
def updataUser(self):
pass
@abstractmethod #抽象方法
def getUser(self):
pass
class UserTest(UserDao): #继承抽象类
def addUser(self):
print("添加用户")
def deletUser(self):
print("删除用户")
def updataUser(self):
print("修改用户")
def getUser(self):
print("查询用户")
test = UserTest()
test.addUser()
test.deletUser()
test.updataUser()
test.getUser()
运行结果:
添加用户
删除用户
修改用户
查询用户
特征三:多态
多态指的是不同对象对同一方法做出的不同相应,具体来说,多态允许我们使用相同的接口(方法名)来操作不同的对象,而这些对象会根据它们自己的类型来执行相应的行为。
python中处处是多态,多态可以增加代码的灵活度,这里简单写一个案例:
class Dog:
def __init__(self,name):
self.name = name
def game(self):
print("名字为 %s 的狗在玩耍..."%self.name)
class JinMaoDog(Dog):
pass
class Taidi(Dog):
pass
class Person:
def __init__(self,name):
self.name = name
def playWithDog(self,dog):
print("%s 与 %s 正在快乐地玩耍.."%(self.name,dog.name))
dog = Dog("流浪狗")
jinmao = JinMaoDog("金毛")
taidi = Taidi("泰迪")
zs = Person("张三")
jinmao.game()
zs.playWithDog(dog)
运行结果:
名字为 金毛 的狗在玩耍...
张三 与 流浪狗 正在快乐地玩耍..

2105

被折叠的 条评论
为什么被折叠?



