八类
Posted aaron-zhou
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了八类相关的知识,希望对你有一定的参考价值。
目录
1. 类的分类
类分为新式类和经典类(基于Python2.x版本来说的,Python3.x版本中只有新式类。)
1.1 经典类
class Family:
def __init__(self):
pass
1.2 新式类
class Family(object):
pass
1.3 新式类和经典类的区别
# 在Python2中,继承了object的就是新式类,默认的是经典类;
# 在Python3中,都是新式类,默认继承了object(注意:为了程序又更好的向下兼容性,在Python3中定义类时,建议都写成class Family(object)这种格式,而不是class Family这种格式;
# 新式类支持super语法,经典类不支持;
# 在多继承中,新式类采用的是广度优先的查找方法,经典类采用的是深度优先的查找方法;
# 新式类有mro方法,经典类没有mro方法。
2. 类和对象
类和对象是面向对象编程的两个重要元素,在此之前,我们进行编码都是面向过程编程的。对象是类的实例化,一个类可以存在多个对象。
class Family(object):
pass
obj = Family()
# obj就是Family类的一个对象,上述obj = Family()的过程称为类的实例化。
3. 类的成员
3.1 类的公有成员
class Family(object):
# 公有属性
family_name = '赵'
# 公有绑定方法
def income(self):
print(self.family_name + '姓家庭的收支')
# 公有普通方法
def pay():
print('每月固定支出')
# Family类的实例化对象obj
obj = Family()
# 类调用公有属性
print(Family.family_name)
# 类不能调用公有绑定方法
# Family.income()
# TypeError: income() missing 1 required positional argument: 'self'
# 类调用公有普通方法
Family.pay()
# 对象调用公有属性
print(obj.family_name)
# 对象调用公有绑定方法
obj.income()
# 对象不能调用公有普通方法
# obj.pay()
# TypeError: pay() takes 0 positional arguments but 1 was given
# 输出结果
赵
每月固定支出
赵
赵姓家庭的收支
3.2 类的私有成员
# 类的私有成员是以两个连续的下划线'__'开头的字符串命名的,私有成员只能在该类内部使用,其实例化对象和派生类都不能使用。
class Family(object):
# 私有属性
__family_money = 1000000
# 私有方法
def __save(self):
print('家庭的储蓄:', self.__family_money)
# 注意:通过_类名__私有成员名的方式可以强行调用类中的私有成员。
4. 类中的方法
4.1 类中的普通方法
# 类中的普通方法是指:在类中定义的没有参数的函数,只有类自身可以调用,对象不能调用。
class Family(object):
def income():
print('I am a normal method.')
Family.income()
obj = Family()
obj.income()
# 输出结果
I am a normal method.
Traceback (most recent call last):
File "E:/python/pycharm/demo/advance/11类中的方法.py", line 12, in <module>
obj.income()
TypeError: income() takes 0 positional arguments but 1 was given
4.2 类中的静态方法
# 类中的静态方法是指:用staticmethod装饰器修饰的普通方法,类自身和对象都能调用。
class Family(object):
@staticmethod
def income():
print('I am a static method.')
Family.income()
obj = Family()
obj.income()
# 输出结果
I am a static method.
I am a static method.
4.3 类中的绑定方法
- 绑定到对象
# 类中的绑定到对象的方法是指:在类中定义的第一个参数为self的函数,该方法只能对象调用,类自身不能调用。
class Family(object):
def income(self):
print('I am a object method.')
obj = Family()
obj.income()
Family.income()
# 输出结果
I am a object method.
Traceback (most recent call last):
File "E:/python/pycharm/demo/advance/11类中的方法.py", line 11, in <module>
Family.income()
TypeError: income() missing 1 required positional argument: 'self'
- 绑定到类
# 类中的绑定到类的方法是指:在类中定义的第一个参数为cls且用装饰器classmethod修饰的函数,该方法对象和类自身都能调用。
class Family(object):
@classmethod
def income(cls):
print('I am a class method.')
obj = Family()
obj.income()
Family.income()
# 输出结果
I am a class method.
I am a class method.
- property装饰器
# property装饰器的作用:将类中的方法变为属性,使得在调用时直接按照调用属性的方式调用该方法,并返回该方法的返回值。
class Family(object):
@property
def income(self):
print('I am property.')
return 12345
obj = Family()
result = obj.income
print(result)
# 输出结果
I am property.
12345
4.4 类中的魔法方法
? Python中,以两个下划线__
开头且以两个下划线__
结尾的方法称为魔法方法。
__new__
、__init__
和__call__
# __new__魔法方法:用于创建空对象,称为“构造方法”;最先被调用,所有的类都继承了object类,该类中包含了__new__方法,需要重写时在自己的类中重新定义__new__即可。 # __init__魔法方法:用来对象赋值,称为“初始化方法”,在__new__方法之后被调用。 # __call__魔法方法:对象后面加括号,会自动调用__call__方法。 class ClassA(object): def __init__(self): print('用于给对象赋值,初始化方法') def __new__(cls, *args, **kwargs): print('用于创建空对象,构造方法') return object.__new__(cls) def __call__(self, *args, **kwargs): print('执行call方法') obj1 = ClassA() # 对象后面加括号,会自动调用__call__方法 obj1() # 输出结果 用于创建空对象,构造方法 用于给对象赋值,初始化方法 执行call方法
__setitem__
、__getitem
和__delitem__
class ClassB(object): def __setitem__(self, key, value): # 'k1'传给key, 123传给value print(key, value) def __getitem__(self, item): # 'xxx'传给item print(item) def __delitem__(self, key): # 'ttt'传给key print(key) obj2 = ClassB() obj2['k1'] = 123 # 内部会自动调用 __setitem__方法 obj2['xxx'] # 内部会自动调用 __getitem__方法 del obj2['ttt'] # 内部会自动调用 __delitem__方法 # 输出结果 k1 123 xxx ttt
__str__
class ClassC(object): def __str__(self): ''' 只有在打印对象时,会自动调用此方法,并将其返回值在页面显示出来 :return: 返回一个字符串 ''' return 'i can only return a string.' obj3 = ClassC() print(obj3, type(obj3)) # 输出结果 i can only return a string. <class '__main__.ClassC'>
__dict__
、__doc__
和__module__
class ClassD(object): '''用来说明__dict__、__doc__和__module__的作用''' def __init__(self, name, age, email): self.name = name self.age = age self.email = email obj4 = ClassD('aaron', 19, '163.com') # 去对象中找到所有对象,并转化为字典 result = obj4.__dict__ print(result) # 得到当前类的说明文档 result = obj4.__doc__ print(result) # 得到当前操作的区域 result = obj4.__module__ print(result) # 输出结果 {'name': 'aaron', 'age': 19, 'email': '163.com'} 用来说明__dict__、__doc__和__module__的作用 __main__
__add__
、__sub__
和__mul__
class ClassE(object): def __add__(self, other): return '两个对象相加时我被调用了' def __sub__(self, other): return '两个对象相减时我被调用了' def __mul__(self, other): return '两个对象相乘时我被调用了' obj5 = ClassE() obj6 = ClassE() result = obj5 + obj6 print(result) result = obj5 - obj6 print(result) result = obj5 * obj6 print(result) # 输出结果 两个对象相加时我被调用了 两个对象相减时我被调用了 两个对象相乘时我被调用了
5. 类的继承
5.1 单继承
# 单继承是指:只继承了一个基类(父类)的派生类(子类);基类的公有成员可以由派生类随意调用。
class Father(object):
def father(self):
print('I am father.')
# 继承了Father类
class Son(Father):
def son(self):
print('I am son.')
obj = Son()
obj.son()
obj.father()
# 输出结果
I am son.
I am father.
5.2 多继承
# 多继承是指:继承了两个及以上的基类的派生类;基类的公有成员可以由派生类随意调用。
class Father(object):
def father(self):
print('I am father.')
class Mother(object):
def mother(self):
print('I am mother.')
# 继承了Father类和Mother类
class Son(Father, Mother):
def son(self):
print('I am son.')
obj = Son()
obj.son()
obj.father()
obj.mother()
# 输出结果
I am son.
I am father.
I am mother.
- issubclass和isinstance
# issubclass:判断指定类是否为某个类的派生类
# isinstance:判断指定对象是否为某个类的实例话对象
class Grandfather(object):
def grandfather(self):
print('I am grandfather.')
class Father(Grandfather):
def father(self):
print('I am father.')
class Aunt(object):
def anut(self):
print('I am aunt.')
class Son(Father):
def son(self):
print('I am son.')
# 判断指定类是否为某个类的派生类
result = issubclass(Son, Father)
print(result)
result = issubclass(Son, Grandfather)
print(result)
result = issubclass(Son, Aunt)
print(result)
obj = Son()
# 判断指定对象是否为某个类的实例话对象
result = isinstance(obj, Son)
print(result)
result = isinstance(obj, Father)
print(result)
result = isinstance(obj, Grandfather)
print(result)
result = isinstance(obj, Aunt)
print(result)
# 输出结果
True
True
False
True
True
True
False
- super()调用父类方法
# super是一个类;super()是一个对象,用于根据mro列表调用下一个类的绑定方法。
# super的作用:派生类中出现基类中的同名绑定方法时,可以既调用派生类中的方法,又调用基类中的方法。
class Grandfather(object):
def money(self):
print("grandfather")
class Father(Grandfather):
def money(self):
print("father1")
super().money()
print("father2")
class Mother(Grandfather):
def money(self):
print("mother1")
super().money()
print("mother2")
class Son(Father, Mother):
def money(self):
print('son1')
super().money()
print('son2')
# 获取使用mro列表
find_list = Son.mro()
print(find_list)
obj = Son()
obj.money()
# 输出结果
[<class '__main__.Son'>, <class '__main__.Father'>, <class '__main__.Mother'>, <class '__main__.Grandfather'>, <class 'object'>]
son1
father1
mother1
grandfather
mother2
father2
son2
# 注意:新式类才支持super和mro方法,mro列表是根据C3算法计算出来的顺序列表,用在多继承中super调用各个类中的同名方法时参照的顺序。
- 深度优先和广度优先
# 在多继承中,调用类中的同名方法时采用的查找方法分为深度优先和广度优先。
# Python2.x:采用深度优先
# Pyhton3.x:采用广度优先
class Grandfather(object):
def money(self):
print("I am grandfather's money.")
class Father(Grandfather):
pass
class Mother(Grandfather):
def money(self):
print("I am mother's money.")
class Son(Father, Mother):
pass
obj = Son()
obj.money()
# 输出结果
# Python2.x:I am grandfather's money.
# Python3.x:I am mother's money.
5.3 约束
'''
若在基类中有一个定义了一个方法如下所示:
def sex(self):
raise NotImplementedError()
若存在派生类类继承了该基类,则,派生类中必须定义一个sex方法!
'''
class Father(object):
def sex(self):
raise NotImplementedError()
class Son(Father):
pass
class Daughter(Father):
def sex(self):
print('I am a girl.')
obj1 = Daughter()
obj1.sex()
obj2 = Son()
obj2.sex()
# 输出结果
I am a girl.
Traceback (most recent call last):
File "E:/python/pycharm/demo/advance/13约束.py", line 22, in <module>
obj2.sex()
File "E:/python/pycharm/demo/advance/13约束.py", line 7, in sex
raise NotImplementedError()
NotImplementedError
5.4 反射
根据字符串的形式去某个对象中操作其成员。
getattr(对象, "字符串")
# 根据字符串去指定对象中获取对应和字符串相同名称的成员。 class Father(object): def __init__(self, money): self.money = money def house(self): print(self.money) obj = Father(12345) # 获取属性 result = getattr(obj, 'money') print(result) # 获取方法 result = getattr(obj, 'house') result() # 输出结果 12345 12345
hasattr(对象, "字符串")
# 根据字符串判定指定对象中是否有对应和字符串相同名称的成员。 class Father(object): def __init__(self, money): self.money = money def house(self): print(self.money) obj = Father(12345) result = hasattr(obj, 'money') print(result) result = hasattr(obj, 'house') print(result) result = hasattr(obj, 'car') print(result) # 输出结果 True True False
setattr(对象, "变量名", "值")
# 在指定对象中设置成员。 class Father(object): def __init__(self, money): self.money = money def house(self): print(self.money) obj = Father(12345) setattr(obj, 'family_name', 'Lions') print(obj.family_name) # 输出结果 Lions
delattr(对象, "字符串")
# 删除指定对象中对应和字符串相同名称的成员。 class Father(object): def __init__(self, money): self.money = money def house(self): print(self.money) obj = Father(12345) result = hasattr(obj, 'money') print('执行delattr之前', result) delattr(obj, 'money') result = hasattr(obj, 'money') print('执行delattr之后', result) # 输出结果 执行delattr之前 True 执行delattr之后 False
5.5 单例模式
无论实例化多少次,都用第一次创建的那个对象。
- 格式
class Singleton(object):
__obj = None
def __new__(cls, *args, **kwargs):
if cls.__obj is None:
cls.__obj = object.__new__(cls)
return cls.__obj
obj1 = Singleton()
print(obj1)
obj2 = Singleton()
print(obj2)
# 输出结果
<__main__.Singleton object at 0x000001B7952E34E0>
<__main__.Singleton object at 0x000001B7952E34E0>
- 例子
class Singleton(object):
__obj = None
def __init__(self, name):
self.name = name
def __new__(cls, *args, **kwargs):
if cls.__obj is None:
cls.__obj = object.__new__(cls)
return cls.__obj
obj1 = Singleton('Aaron')
obj2 = Singleton('Joe')
print(obj1.name)
print(obj2.name)
# 输出结果
Joe
Joe
# 注意:obj1和obj2是同一个对象,所以obj1.name和obj2.name是同一个值。
'''
若将上例代码中的:
obj2 = Singleton('Joe')
print(obj1.name)
两行位置互换,则输出结果为:
Aaron
Joe
'''
6. 面向对象三大特征
6.1 封装
对类中成员属性和方法的保护,控制外界对内部成员的访问、修改、删除等操作。
6.2 继承
一个类除了自身所拥有的属性方法之外,还获取了另一个类的成员属性和方法。
6.3 多态
不同的子类对象,调用相同的父类方法,产生不同的执行结果。
以上是关于八类的主要内容,如果未能解决你的问题,请参考以下文章