类和对象的概念:
- 类:在python中,类是通过class进行创建的,它是将一些特征和方法进行封装,以适用于具有同样特征的对象。它更像是一个模板,通过输入不同的变量,创建出不同的具体对象。
- 对象:在python中,万物皆是对象。它是类的实例化,是将变量传入类中,所构建出来的具体对象。如果说类是“人类”的话,那么对象就是具有特定名称,特定行为的“张三”,"李四“。
类实例化成对象的过程
#在以下示例中,person就是类,传入参数后形成的lisi属于对象
class person(object):
def __new__(cls):
return object.__new__(cls)
def __init__(self,name,age):
self.name = name
self.age = age
def run(self):
print("{}可以跑".format(self.name))
#类实例化对象的过程:
# 1.首先调用__new__()方法,在内存中申请一块空间;
# 2.然后调用__init__()方法,进行初始化配置;
# 3.将对象lisi指向所申请的内存空间
lisi = person("李四",20)
lisi.run()
魔法方法
在python中有这么一种方法,它们以"__“开始,以”__"结束,不用手动调用,系统会在合适的时间自行调用,他们类似于关键字都是系统规定好的名称。
class person(object):
#__init__()在对象创建时被调用
def __init__(self,name,age):
print("对象被创建")
self.name = name
self.age = age
#__str__()在对象打印时进行调用
def __str__(self):
return self.name
#__del__()在对象被删除时进行调用
def __del__(self):
print("删除的时候调用")
#我们可以看到,当对象进行不同的动作时,系统自动调用了相应的魔法方法
a = person("dog",5) >>> 对象被创建
print(a) >>> dog
del a >>> 删除的时候调用
常见的魔法方法以及适用场景
魔法方法 | 调用场景 |
---|---|
_init_() | 创建对象时,被调用 |
_str_() | 打印对象时,被调用,必须返回一个字符串 |
_del_() | 删除对象时,被调用 |
_eq_() | 进行”==“比较运算时,被调用 |
_repr_() | 打印对象时,被调用 |
_call_() | 对象被当作函数调用时,被调用 |
_ne_() | 进行”!=“比较运算时,被调用 |
类的内置属性
class person(object):
"""
这是一个类的注释
"""
def __init__(self,name,age):
print("对象被创建")
self.name = name
self.age = age
a = person("李四",20)
#使用dir()查看对象a的内置属性
print(dir(a))
['__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__', 'age', 'name']
#__class__属性展示对象所属的类
print(a.__class__) >>> <class '__main__.person'>
#__dict__属性是将对象的变量以字典的形式展示出来
print(a.__dict__) >>> {'name': '李四', 'age': 20}
#__doc__属性展示对象a的注释
print(a.__doc__) >>> 这是一个类的注释
#__eq__,__ge__,__gt__,__lt__,__le__,__ne__做比较运算时自行调用
#__dir__等同于dir()
#__module__返回模块的名称,直接运行模块,为__main__
#__repr__,__str__打印内容,打印时自行调用
#__new__,__init__创建对象时,自行调用
#其他不常用,可自行了解
私有变量和私有方法
class person(object):
def __init__(self,name,age):
self.name = name
self.age = age
#以"__“开始的变量为私有变量,只能内部访问
self.__sex = "男"
def __fun(self):
print("私有方法")
a = person("wwl",20)
#可以看到,name,age属性是可以在外部访问到的
print(a.name,a.age) >>> wwl 20
#而私有变量__sex在外部不能直接访问
print(a.__sex) >>> AttributeError: 'person' object has no attribute '__sex'
#私有变量可以使用对象._类__私有变量名的形式获取到
print(a._person__sex) >>> 男
#同私有变量一样,私有方法也是无法直接调用的
a.__fun() >>> AttributeError: 'person' object has no attribute '__fun'
#虽然无法直接调用,但可以通过对象._类__私有方法名的形式进行调用
a._person__fun() >>> 私有方法
对象方法的调用
class person(object):
def __init__(self,name,age):
self.name = name
self.age = age
#常规方法为对象方法
def like(self,thing):
print("{}喜欢{}".format(self.name,thing))
a = person("张三",20)
b = person("李四",21)
#对象方法的调用注意点:
#1.like()函数的内存是在person类中,调用a.like()和b.like()时,是引用的person类中函数,对象a,b中是没有单独的函数内存的;
print(id(a.like)) >>> 2318914940992
print(id(b.like)) >>> 2318914940992
#2.虽然两者引用的都是类中的like()函数,但a.like()与b.like()是两个不同的函数
print(a.like) >>> <bound method person.like of <__main__.person object at 0x000001BF54407400>>
print(a.like) >>> <bound method person.like of <__main__.person object at 0x000001BF544158B0>>
#3.调用like()函数有两种方法,一种是通过对象调用;一种是通过类来调用
#通过对象调用时,系统自动将对象a传递给self,只需给出其他变量即可
a.like("跑步") >>> 张三喜欢跑步
#通过类调用时,系统不会自动传参给self,需要自己指定变量
person.like(a,"跑步") >>> 张三喜欢跑步
类方法和静态方法
class person(object):
#__new__方法虽然参数是cls,但是它是一个静态方法
def __new__(cls):
return object.__new__(cls)
def __init__(self,name,age):
self.name = name
self.age = age
#如果一个方法中,没有用到实例对象的任何属性,可以将此方法定义成静态方法
@staticmethod
def like():
print("我喜欢跑步")
#如果一个方法中,只用到了类属性,可以将此方法定义成类方法
@classmethod
def test(cls):
print("类方法")
a = person("张三",20)
#静态方法和类方法的调用:既可以通过实例对象调用,也可以通过类来调用
a.like() >>> 我喜欢跑步
person.like() >>> 我喜欢跑步
a.test() >>> 类方法
person.test() >>> 类方法
单例模式
class person(object):
__instance = None
def __new__(cls,*args,**kwargs):
if cls.__instance is None:
cls.__instance = object.__new__(cls)
return cls.__instance
def __init__(self,name,age):
self.name = name
self.age = age
a = person("张三",20)
b = person("李四",21)
#单例模式:是指一个类只能创建一个实例对象,后续对象的创建只会覆盖之前的对象
print(a.name) >>> 李四
print(b.name) >>> 李四
继承
class car(object):
def __init__(self,color,width):
self.color = color
self.width = width
def test(self):
print("{}".format(self.color))
class vehicle(object):
def test(self):
print("{}".format(self.height))
class suv(car):
def __init__(self,color,width,height,weight):
#子类在父类的基础上,增加自己特有的功能
#调用父类方法的两种方式:
#1.通过父类名.方法名(self,参数列表)调用
#car.__init__(self,color.width)
#2.通过super直接调用父类的方法
super(suv,self).__init__(color,width)
self.height = height
self.weight = weight
class mpv(car,vehicle):
pass
a = car("yellow",1450)
b = suv("blue",1550,175,1000)
c = mpv("red",1650)
#可以看到实例对象b拥有car的属性,suv在继承car的基础上,还额外增加了weight和height属性
print(b.weight) >>> 1000
print(b.height) >>> 175
#当子类没有方法时,会寻找其父类
b.test() >>> blue
#对于多继承方法的查找原则为深度优先,当自身没有相应的方法时,寻找第一父类,如果父类没有,再寻其父类,直至根源,若根源仍没有,则寻找第二父类,依此类推。
c.test() >>> red
#继承需要注意,父类的私有属性和私有方法,子类不会继承
多态
#多态是基于继承,通过子类重写父类的方法,达到不同的子类调用相同的父类方法,得到不同的效果
#python中通过重写可以达到多态,可以提高代码的灵活度
class car(object):
def feature(self):
print("汽车可以跑")
class tesla(car):
def feature(self):
print("自动驾驶很厉害")
class xiaopeng(car):
def feature(self):
print("高科技比较多")
class jihu(car):
def feature(self):
print("造型比较好看")
class apeal(object):
def __init__(self, car):
self.car = car
def evaluate(self):
if isinstance(self.car, car):
self.car.feature()
else:
print("不在评价车型内")
a = jihu()
b = tesla()
apeal(a).evaluate() >>> 造型比较好看
apeal(b).evaluate() >>> 自动驾驶很厉害
#使用了多态后,后面如果还评价其他车型,只需在增加一个car的子类即可,其他代码都不用修改,灵活度比较高