面向对象主要包含,类和对象。类就是一类对象抽象出来的,是具有相同属性和行为事物的统称。我们的类主要分为:类名、属性、方法,下面主要以这三点进行概述。在类的高级使用主要是以面向对象的三大特性来介绍:封装、继承、多态。主要是以继承来介绍。
基本格式
class 类名:
方法列表
在python2 分为新式类和经典类。但是在python3中默认都是新式类,继承的是object
demo
class Demo():
name = "yuge" #类属性
def __init__(self):
self.user_name = "rookie" # 实例属性
def func(self): # 类方法 后面会有介绍
pass
对象创建
d = Demo()
一个类可以创建多个对象。
比如说桌子是一个类,属性就是颜色、大小。它的方法就是它的作用。
那么可以跟着这个对象创建出不同的桌子,学生桌、饭桌等。那么创建出来的集体的桌子就是对象了。
一、类名
类名定义遵循PEP8规范,大驼峰命名法。
二、属性
1、类属性
在上面的demo中 name 就是类属性,在创建出来的所有对象中都可以使用。
添加
添加有三种方式,
1)直接在类里面添加,在类方法上面
2)直接使用 类对象名.属性名 Demo.name ="rooke"
3)使用类方法用 cls.属性名
调用:
类名.属性名
对象.属性名 注意:如果有实例属性和类属性同名,在调用时会使用类属性
2、实例属性
我们再开发中用的最多的就是实例属性,所谓实例属性就是创建实例对象所独立拥有的,每个对象所创建的实例属性互不相干。
3、私有属性
私有属性即为在外部不能访问的属性,只有在本类中使用的属性。实例属性和类属性都可以设置为私有属性。
私有属性就是在属性前面加上两个下划线 __name
demo
class Demo()
def __init__(self):
self.__name = "rookie" #定义私有属性
d = Demo()
print(d.__name) #当我们去打印的时候无法获取到私有属性。
添加
1)在方法中
自己方法中添加
自己定义的方法中可以使用 self.属性名 = 变量 赋值添加
__init__(self) 中添加
__init__ 方法是魔法方法,每次创建对象后进行初始化操作,在这里我们进行初始化属性。
self.属性名 = 变量 赋值添加
在使用__init__方法时,可以接收参数来进行初始化
demo:
class Demo():
name = "yuge" #类属性
def __init__(self,name): #接收传来的参数
self.user_name = name # 实例属性进行保存使用
d = Demo("rookie") #在创建时需要传递参数
在__init__,也可以传入不定长参数,默认参数,和方法的使用一样,只不过第一个参数必须是self
self:指的是本类,我们也可以理解为:谁调用的我(创建的实例对象是谁)那么self指的就是谁
所谓的self,可以理解为自己
可以把self当做C++中类里面的this指针一样理解,就是对象自身的意思
某个对象调用其方法时,python解释器会把这个对象作为第一个参数传递给self,所以开发者只需要传递后面的 参数即可。
self仅仅是一个变量名,也可将self换为其他任意的名字,但是为了能够让其他开发人员能明白这变量的意思,因此一般都会self当做名字。
2)对象名.属性赋值
调用
对象名.属性名
在self中保存的实例属性,那么在本类中所有方法都可以进行使用 self.属性名
三、方法
1、实例方法
实例方法就是一个类里面创建的方法,它的使用和函数的使用几乎相同。只不过在穿件实例方法的时候第一个参数时self(一般我们都是用的self,指的是自己)。传参和返回值和函数使用一样。
在调用的时候使用 对象名.方法名
demo
class Demo():
def func(self): #定义方法
print("rookie 写代码")
d = Demo() #创建对象
d.func() #调用实例方法
2、类方法
类方法是在实例方法上面加上@classmethod装饰器,传入的self修改为cls参数。一般情况下类方法是用来修改类属性的。类属性一般定义为私有属性。在使用的时候可以 类名.方法名 也可以 类对象.方法名 来调用
3、静态方法
静态方法的使用比较少,就是在实例方法的上面加上@staticmethod装饰器,方法里面不用传递self、cls参数。使用的时候和类方法类似。当方法不需要用到类中的属性时候可以使用,因为它没有self、cls参数。
4、魔法方法
上边提到的初始化__itit__()方法的时候就是一个魔法方法,魔法方法是类中定义的方法,由类自己调用,不需要我们自己手动调用的方法,一般情况格式为__名字__()
__init__(self[, ...])
构造器,当一个实例被创建的时候调用的初始化方法
__new__(cls[, ...])
1. __new__ 是在一个对象实例化的时候所调用的第一个方法
2. 它的第一个参数是这个类,其他的参数是用来直接传递给 __init__ 方法
3. __new__ 决定是否要使用该 __init__ 方法,因为 __new__ 可以调用其他类的构造方法或者直接返回别的实例对象来作为本类的实例,如果 __new__ 没有返回实例对象,则 __init__ 不会被调用
4. __new__ 主要是用于继承一个不可变的类型比如一个 tuple 或者 string
__del__(self)
析构器,当一个实例被销毁的时候调用的方法
__call__(self[, args...])
允许一个类的实例像函数一样被调用:x(a, b) 调用 x.__call__(a, b) 当我们创建一个对象后可以直接进行 对象() 会直接调用__call__方法
__len__(self)
定义当被 len() 调用时的行为
__repr__(self)
定义当被 repr() 调用时的行为,和__str__ 类似
__str__(self)
定义当被 str() 调用时的行为。我们可以直接打印对象名,会调用__str__方法
__bool__(self)
定义当被 bool() 调用时的行为,应该返回 True 或 False
以上是基础的魔法方法 还有更多的魔法方法
__bytes__(self)定义当被 bytes() 调用时的行为
__hash__(self)定义当被 hash() 调用时的行为
__format__(self, format_spec)定义当被 format() 调用时的行为
__getattr__(self, name)定义当用户试图获取一个不存在的属性时的行为
__getattribute__(self, name)定义当该类的属性被访问时的行为
__setattr__(self, name, value)定义当一个属性被设置时的行为
__delattr__(self, name)定义当一个属性被删除时的行为
__dir__(self)定义当 dir() 被调用时的行为
__get__(self, instance, owner)定义当描述符的值被取得时的行为
__set__(self, instance, value)定义当描述符的值被改变时的行为
__delete__(self, instance)定义当描述符的值被删除时的行为
比较操作符
__lt__(self, other)定义小于号的行为:x < y 调用 x.__lt__(y)
__le__(self, other)定义小于等于号的行为:x <= y 调用 x.__le__(y)
__eq__(self, other)定义等于号的行为:x == y 调用 x.__eq__(y)
__ne__(self, other)定义不等号的行为:x != y 调用 x.__ne__(y)
__gt__(self, other)定义大于号的行为:x > y 调用 x.__gt__(y)
__ge__(self, other)定义大于等于号的行为:x >= y 调用 x.__ge__(y)
算数运算符
__add__(self, other)定义加法的行为:+
__sub__(self, other)定义减法的行为:-
__mul__(self, other)定义乘法的行为:*
__truediv__(self, other)定义真除法的行为:/
__floordiv__(self, other)定义整数除法的行为://
__mod__(self, other)定义取模算法的行为:%
__divmod__(self, other)定义当被 divmod() 调用时的行为
__pow__(self, other[, modulo])定义当被 power() 调用或 ** 运算时的行为
__lshift__(self, other)定义按位左移位的行为:<<
__rshift__(self, other)定义按位右移位的行为:>>
__and__(self, other)定义按位与操作的行为:&
__xor__(self, other)定义按位异或操作的行为:^
__or__(self, other)定义按位或操作的行为:|
反运算
__radd__(self, other)(与上方相同,当左操作数不支持相应的操作时被调用)
__rsub__(self, other)(与上方相同,当左操作数不支持相应的操作时被调用)
__rmul__(self, other)(与上方相同,当左操作数不支持相应的操作时被调用)
__rtruediv__(self, other)(与上方相同,当左操作数不支持相应的操作时被调用)
__rfloordiv__(self, other)(与上方相同,当左操作数不支持相应的操作时被调用)
__rmod__(self, other)(与上方相同,当左操作数不支持相应的操作时被调用)
__rdivmod__(self, other)(与上方相同,当左操作数不支持相应的操作时被调用)
__rpow__(self, other)(与上方相同,当左操作数不支持相应的操作时被调用)
__rlshift__(self, other)(与上方相同,当左操作数不支持相应的操作时被调用)
__rrshift__(self, other)(与上方相同,当左操作数不支持相应的操作时被调用)
__rxor__(self, other)(与上方相同,当左操作数不支持相应的操作时被调用)
__ror__(self, other)(与上方相同,当左操作数不支持相应的操作时被调用)
增量赋值运算
__iadd__(self, other)定义赋值加法的行为:+=
__isub__(self, other)定义赋值减法的行为:-=
__imul__(self, other)定义赋值乘法的行为:*=
__itruediv__(self, other)定义赋值真除法的行为:/=
__ifloordiv__(self, other)定义赋值整数除法的行为://=
__imod__(self, other)定义赋值取模算法的行为:%=
__ipow__(self, other[, modulo])定义赋值幂运算的行为:**=
__ilshift__(self, other)定义赋值按位左移位的行为:<<=
__irshift__(self, other)定义赋值按位右移位的行为:>>=
__iand__(self, other)定义赋值按位与操作的行为:&=
__ixor__(self, other)定义赋值按位异或操作的行为:^=
__ior__(self, other)定义赋值按位或操作的行为:|=
一元操作符
__neg__(self)定义正号的行为:+x
__pos__(self)定义负号的行为:-x
__abs__(self)定义当被 abs() 调用时的行为
__invert__(self)定义按位求反的行为:~x
类型转换
__complex__(self)定义当被 complex() 调用时的行为(需要返回恰当的值)
__int__(self)定义当被 int() 调用时的行为(需要返回恰当的值)
__float__(self)定义当被 float() 调用时的行为(需要返回恰当的值)
__round__(self[, n])定义当被 round() 调用时的行为(需要返回恰当的值)
__index__(self)1. 当对象是被应用在切片表达式中时,实现整形强制转换
2. 如果你定义了一个可能在切片时用到的定制的数值型,你应该定义 __index__
3. 如果 __index__ 被定义,则 __int__ 也需要被定义,且返回相同的值
上下文管理(with 语句)
__enter__(self)1. 定义当使用 with 语句时的初始化行为
2. __enter__ 的返回值被 with 语句的目标或者 as 后的名字绑定
__exit__(self, exc_type, exc_value, traceback)1. 定义当一个代码块被执行或者终止后上下文管理器应该做什么
2. 一般被用来处理异常,清除工作或者做一些代码块执行完毕之后的日常工作
容器类型
__len__(self)定义当被 len() 调用时的行为(返回容器中元素的个数)
__getitem__(self, key)定义获取容器中指定元素的行为,相当于 self[key]
__setitem__(self, key, value)定义设置容器中指定元素的行为,相当于 self[key] = value
__delitem__(self, key)定义删除容器中指定元素的行为,相当于 del self[key]
__iter__(self)定义当迭代容器中的元素的行为
__reversed__(self)定义当被 reversed() 调用时的行为
__contains__(self, item)定义当使用成员测试运算符(in 或 not in)时的行为
封装
将不同的方法,封装到一个类里面从而完成一个功能。
继承
将父类的属性和方法给子类使用
私有的属性,不能通过对象直接访问,但是可以通过方法访问
私有的方法,不能通过对象直接访问
私有的属性、方法,不会被子类继承,也不能被访问
一般情况下,私有的属性、方法都是不对外公布的,往往用来做内部的事情,起到安全的作用
父类中的 私有方法、属性,不会被子类继承
可以通过调用继承的父类的共有方法,间接的访问父类的私有方法、属性
单继承
子类在继承的时候,在定义类时,小括号()中为父类的名字
父类的属性、方法,会被继承给子类
demo
class F(): #定义父类
def func(self):
print("rookie yu")
class S(F): #子类继承
pass
S.func()
上边的代码我们可以看到,子类完全没有写任何方法,但是我们可以调用fcun方法,就是因为继承父类。
当我们使用子类的时候,有的时候子类的方法名和父类相同,那么就会重写父类的方法,再次调用的时候回调用子类的方法,不会调用父类写的方法。
class F(): #定义父类
def func(self):
print("rookie yu")
class S(F): #子类继承
def func():
print("rookie yu sun")
s = S()
s.func()
我们可以看到,当我们使用时,直接使用的就是子类的方法
当我们的方法和父类不一样的时候,那么就是给子类增加方法。那时候我们的子类既有父类的方法属性,也有自己独特的方法和属性。
super
当我们使用子类的时候重写了父类的方法,同时还需要父类的方法,那么我们就需要使用super
demo:
class F(): #定义父类
def func(self):
return "rookie yu"
class S(F): #子类继承
def func():
name =super(S,self).func() #调用父类方法
# name =super().func() #可以简写
print(name)
S.func()
多层继承
多层继承和单继承相差不多,咱们在上边的例子中S也相当于一个多层继承,因为F类继承的就是object
多继承
多继承这主要是子类对多个类的继承,相当于独生子女可以继承父亲和母亲的所有家产一样,当然还可以有自己的独立的方法和属性。
class A():
def test1(self):
print('----A test----')
# 定义一个父类
class B():
def test2(self):
print('----B test----')
# 定义一个子类,继承自A、B
class C(A,B):
pass
obj_C = C()
obj_C.test1()
obj_C.test2()
print(C.__mro__)#可以查看C类的对象搜索方法时的先后顺序
然而当我们的父类都有同一个方法的时候我们调用的时候到底调用的是哪一个父类的方法呢?
那么我就就要看继承的顺序了,当我们继承的第一个父类中有所有要调用的方法,那么就会使用,如果没有那么就去第二个父类调用。
Mixin扩展类
class F(object): #定义父类
def func(self):
print("rookie yu")
class MyMixin(object): #定义扩展类,继承object
def minxinFunc(self): #扩展类定义方法
self.func()
class S(MyMixin,F): #定义子类 继承F, MyMixin
pass
s = S()
s.minxinFunc() #我们调用MyMixin中的minxinFunc方法
在上面的代码中我们可以看到我们的MyMixin类中没有func方法,MyMixin继承的是object,object也不可能有func方法。但是我们用的却是self.func()却执行到了,就是因为子类在继承的时候继承了两个父类F类中有func方法,解释器在解析时,在调用方法时,记录了F类中的方法,MyMixin就可以使用到这个方法了。
多态
多态的概念是应用于Java和C#这一类强类型语言中,而Python崇尚“鸭子类型”。
所谓多态:定义时的类型和运行时的类型不一样,此时就成为多态
class F1(object):
def show(self):
print('F1.show')
class S1(F1):
def show(self):
print('S1.show')
class S2(F1):
def show(self):
print('S2.show')
# 为了让Func函数既可以执行S1对象的show方法,又可以执行S2对象的show方法,所以,定义了一个S1和S2类的父类
# 而实际传入的参数是:S1对象和S2对象
def Func(obj):
"""Func函数需要接收一个F1类型或者F1子类的类型"""
obj.show()
s1_obj = S1()
Func(s1_obj)# 在Func函数中传入S1类的对象 s1_obj,执行 S1 的show方法,结果:S1.show
s2_obj = S2()
Func(s2_obj)# 在Func函数中传入Ss类的对象 ss_obj,执行 Ss 的show方法,结果:S2.show
其他(内部类)
class Wapper(): #定义一个外部类
def wFunc(self):
print("外部类的方法")
class Inner(): #定义一个内部类
def func(self): #内部类的方法
print("我是内部类")
w = Wapper() #创建一个类对象
i = w.Inner() #创建一个内部类对象
i.func() #调用内部类方法
内部类和外部类关系就像汽车和车轮,汽车是一个类,轮胎也可以看做一个类。虽然内部类在外部类里面,但是内部类不能直接使用外部类的方法和属性。外部类可以定义一些类属性,在内部类创建对象进而使用。