简单介绍与创建
类用来描述具有相同的属性和方法的对象的集合。它定义了该集合中每个对象所共有的属性和方法。对象是类的实例
方法:类中的函数
类属性或类变量:类属性在整个实例化的对象中是公用的。类属性定义在类中且在函数体之外。类属性通常不作为实例实例使用。
实例属性或实例变量:在类的声明中,属性是用变量来表示的,这种变量就称为实例变量,实例变量就是一个用 self 修饰的变量,如下方的self.name;
self本身代表的是类实例化后的实例对象,self.name 便是属于实例属性
#coding:utf-8
class People:
'''
A class of People
'''
def __init__(self,name="无名"):
self.name = name
self.gender = 0
self.singular = False
def talk(self):
print("我是",self.name)
#对象实例化
p1 = People()
p1.talk()
print(p1.name)
类属性与实例属性
类属性,又称为静态属性,在方法函数外创建,可直接使用类调用,也可以使用实例化的对象调用;而且可以使用类名.属性名的方式,给类添加类属性;只能够通过类去修改
实例属性,又称为动态属性,通过实例创建,在方法函数中创建且使用self.属性名方式创建,当然也可以使用实例化对象.属性名称来创建,创建出来的未实例属性;不同实例属性值一般不同
当实例属性名与类属性重名时使用实例属性调用时只会优先获取实例属性,即实例属性将类属性覆盖掉;
实例化对象使用__dict__,可以获取当前实例的所有属性,示例如下
>>> class People:
... type = "人"
... def __init__(self,name):
... self.name = name
...
>>> print(People.type)
人
>>> one = People("舜天")
>>> print(one.type)
人
>>> print(one.name)
舜天
>>> People.haseye = True
>>> print(People.haseye)
True
>>> print(one.haseye)
True
>>> one.work="律师"
>>> dir(one)
['__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__', 'haseye', 'name', 'type', 'work']
>>> one.type = "超人"
>>> print(one.type)
超人
>>> print(People.type)
人
>>> one.__dict__
{'name': '舜天', 'work': '律师', 'type': '超人'}
>>>
继承
继承是对象的特性之一;继承是面向对象编程的一个重要概念;如何实现继承,见简单示例代码:
>>> class A:
def __init__(self,name):
self.name = name
def pri(self):
return "我数"
>>> class B(A):
pass
>>> b = B()
Traceback (most recent call last):
File "<pyshell#49>", line 1, in <module>
b = B()
TypeError: __init__() missing 1 required positional argument: 'name'
>>> b=B("我是谁")
>>> b.pri()
'我数'
>>>
继承与重写父类方法,若子类也定义了初始化方法时会将父类的初始化方法覆盖,覆盖之后只会保留了子类的实例属性,而父类的实例属性则丢了,示例:
>>> class B(A):
def __init__(self,age):
self.age = age
>>> b = B()
Traceback (most recent call last):
File "<pyshell#56>", line 1, in <module>
b = B()
TypeError: __init__() missing 1 required positional argument: 'age'
>>> b=B("aaa",5)
Traceback (most recent call last):
File "<pyshell#61>", line 1, in <module>
b=B("aaa",5)
TypeError: __init__() takes 2 positional arguments but 3 were given
>>> b=B(5)
>>> b.pri()
'我数'
>>> b.age
5
>>> b.name
Traceback (most recent call last):
File "<pyshell#60>", line 1, in <module>
b.name
AttributeError: 'B' object has no attribute 'name'
>>>
若要实现继承父类的实例属性,那么需要将父类的初始化方法参数在子类中重新调用才行,可以使用类名.init(self,name)或者super().init(name)如下:
>>> class B(A):
def __init__(self,name,age):
A.__init__(self,name)
self.age = age
>>> b = B(5)
Traceback (most recent call last):
File "<pyshell#73>", line 1, in <module>
b = B(5)
TypeError: __init__() missing 1 required positional argument: 'age'
>>> b = B("我",7)
>>> dir(b)
['__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', 'pri']
另一种写法使用super()调用父类的初始化方法,但是该方法只适用于单继承,即字类定义时括号里只有一个类:
class B(A):
def __init__(self,name,age):
super().__init__(name)
self.age = age
当然重写父类方法的话,不只可以重写父类初始化方法,也可以重写父类的其他方法,依然可以使用super().方法名()方式重写;
实际编程中使用单继承的相对多一些,提倡使用单继承,而通过类的mro方法可以查找当前字类的继承顺序
>>> print(B.__mro__)
(<class '__main__.B'>, <class '__main__.A'>, <class 'object'>)
>>>
多态
多态是面向对象的特性之一
Python语言天然具有多态的特性
>>> def add(x,y):
return x+y
>>> add(1,2)
3
>>> add("a","b")
'ab'
>>>
封装
封装是对象的特性之一,python通过私有化的方式实现封装;类中的属性使用两个下划线“__”实现私有化,无论是实例化后的对象还是原有类对象本身都无法调用;这样在作用域之外就无法调用属性或者方法
>>> class Exemple:
__name = "我是"
book = "python"
>>> Exemple.book
'python'
>>> Exemple.__name
Traceback (most recent call last):
File "<pyshell#5>", line 1, in <module>
Exemple.__name
AttributeError: type object 'Exemple' has no attribute '__name'
>>> e = Exemple()
>>> e.__name
Traceback (most recent call last):
File "<pyshell#7>", line 1, in <module>
e.__name
AttributeError: 'Exemple' object has no attribute '__name'
>>>
其他方法以及实例属性或实例变量私有化示例如下:
>>> class Exe:
def __init__(self,name):
self.___name = "name"
self.nam = name
def __group():
print("group---")
def getname(self):
return self.___name
>>> e = Exe("kkkk")
>>> e.__name
Traceback (most recent call last):
File "<pyshell#32>", line 1, in <module>
e.__name
AttributeError: 'Exe' object has no attribute '__name'
>>> e.getname()
'name'
>>> e.__group()
Traceback (most recent call last):
File "<pyshell#34>", line 1, in <module>
e.__group()
AttributeError: 'Exe' object has no attribute '__group'
定制类
控制属性访问
优化内存__slots__,控制属性特殊方法:getattr__与__setattr
使用__dict__可以找到对应的类属性或者实例属性
>>> class A:
name="我"
>>> A.__dict__
mappingproxy({'__module__': '__main__', 'name': '我', '__dict__': <attribute '__dict__' of 'A' objects>, '__weakref__': <attribute '__weakref__' of 'A' objects>, '__doc__': None})
>>> a = A()
>>> a.__dict__
{}
>>> a.age=25
>>> a.__dict__
{'age': 25}
如何限制类的属性个数与名字,可使用__slots__,加了限制之后,将无法增加限制中的属性
>>> class A:
__slots__ = ("name","age")
>>> a.name="爱因斯坦"
>>> a.word="了不起的人"
Traceback (most recent call last):
File "<pyshell#127>", line 1, in <module>
a.word="了不起的人"
AttributeError: 'A' object has no attribute 'word'
>>> A.word="了不起的人"
>>> a.name = "我"
>>> a.word="12"
Traceback (most recent call last):
File "<pyshell#130>", line 1, in <module>
a.word="12"
AttributeError: 'A' object attribute 'word' is read-only
getattr__与__setattr,使用示例:
>>> class A:
def __getattr__(self,name):
print("使用了getattr")
def __setattr__(self,name,value):
print("使用了setattr方法")
self.__dict__[name] = value
>>> a=A()
>>> a.x
使用了getattr
>>> a.x='a'
使用了setattr方法
>>> a.x
'a'