1. 类的创建
类是一种数据结构,我们可以用它来定义对象,后者把数据值和行为特性融合在一起。类是现实世界的抽象的实体以编程形式出现。实例是这些对象的具体化。
类名通常由大写字母打头。这是标准惯例
class First(): pass if __name__ == '__main__': f = First() f.x = 3 f.y = 5 print(f.x + f.y )
2. 方法
self 参数,它在所有的方法声明中都存在。这个参数代表实例对象本身,当你用实例调用方法时,由解释器悄悄地传递给方法的,所以,你不需要自己传递 self 进来,因为它是自动传入的。
self,它表示调用此方法的实例对象,
调用一个方法的最终途径
(a)定义类(和方法)
(b)创建一个实例
(c)最后一步,用这个实例调用方法。
class First(): def raiseup(self): print("raise it up!") if __name__ == '__main__': f = First() f.x = 3 f.y = 5 print(f.x + f.y ) f.raiseup()
通过类名直接调用方法First.raiseup()
D:PythonPython35python.exe D:/PycharmProjects/pythonOO/ff2.py Traceback (most recent call last): File "D:/PycharmProjects/pythonOO/ff2.py", line 7, in <module> First.raiseup() TypeError: raiseup() missing 1 required positional argument: 'self' Process finished with exit code 1
绑定:
为与 OOP 惯例保持一致, Python 严格要求, 没有实例, 方法是不能被调用的。 这种限制即 Python所描述的绑定概念(binding),在此,方法必须绑定(到一个实例) 才能直接被调用。非绑定的方法可能可以被调用,但实例对象一定要明确给出,才能确保调用成功。然而,不管是否绑定,方法都是它所在的类的固有属性,即使它们几乎总是通过实例来调用的。
调用非绑定方法:
子类调用分类的init,AddrBookEntry.__init__(self, nm, ph)
3. __init__()
Python 创建实例后,在实例化过程中,调用__init__()方法,当一个类被实例化时,就可以定义额外的行为, 比如, 设定初始值或者运行一些初步诊断代码———主要是在实例被创建后,实例化调用返回这个实例之前,去执行某些特定的任务或设置。 最后一句暂不明白
当对象 f被实例化后,它的f.name 就被设置了。
class First():
def __init__(self,name):
self.name = name
print("HI! " + self.name + "! Be prepared for raising it up!")
def raiseup(self):
print("raise it up!")
if __name__ == '__main__':
f = First('Alex')
f.raiseup()
运行
D:PythonPython35python.exe D:/PycharmProjects/pythonOO/first.py HI! Alex! Be prepared for raising it up! raise it up! Process finished with exit code 0
4. 继承
Python 中,当一个类被派生出来,子类继承了基类的属性,所以,在上面的类中,我们不仅定义了__init__(),updatEmail()方法,而且Second还从 First中继承了 raiseup()方法。
如果需要,每个子类最好定义它自己的构造器,不然,基类的构造器会被调用。然而,如果子类重写基类的构造器,基类的构造器就不会被自动调用了--这样,基类的构造器就必须显式写出才会被执行,例如First.__init__(self,name)
这里我们要显式传递 self 实例对象给基类构造器,因为我们不是在其实例中调用那个方法而是在一个子类实例中调用那个方法。因为我们不是通过实例来调用它,这种未绑定的方法调用需要传递一个适当的实例(self)给方法。
class First(): def __init__(self,name): self.name = name print("HI! " + self.name + "! Be prepared for raising it up!") def raiseup(self): print("raise it up!") class Second(First): def __init__(self,name,weapon): First.__init__(self,name) self.weapon = weapon print("HI! " + self.name + "! Be prepared for raising it up! with " + self.weapon ) def raiseupWith(self): print("raise it up! with" + self.weapon) if __name__ == '__main__': s = Second('Alex','Python') s.raiseup() s.raiseupWith()
运行
D:PythonPython35python.exe D:/PycharmProjects/pythonOO/first.py HI! Alex! Be prepared for raising it up! HI! Alex! Be prepared for raising it up! with Python raise it up! raise it up! withPython Process finished with exit code 0
如果不重新子类的__init__,实例化时,可使用父类的__init__
class First(): def __init__(self,name): self.name = name print("HI! " + self.name + "! Be prepared for raising it up!") def raiseup(self): print("raise it up!") class Second(First): def raiseupWith(self): print("raise it up! with" + self.weapon) if __name__ == '__main__': # s = Second('Alex','Python') s = Second('Alex') s.raiseup() s.raiseupWith()
D:PythonPython35python.exe D:/PycharmProjects/pythonOO/first.py
HI! Alex! Be prepared for raising it up!
Traceback (most recent call last):
raise it up!
File "D:/PycharmProjects/pythonOO/first.py", line 25, in <module>
s.raiseupWith()
File "D:/PycharmProjects/pythonOO/first.py", line 18, in raiseupWith
print("raise it up! with" + self.weapon)
AttributeError: 'Second' object has no attribute 'weapon'
Process finished with exit code 1
5. 属性
类的数据属性
数据属性仅仅是所定义的类的变量。它们可以像任何其它变量一样在类创建后被使用,并且,要么是由类中的方法来更新,要么是在主程序其它什么地方被更新。
即静态变量,或者是静态数据。它们表示这些数据是与它们所属的类对象绑定的,不依赖于任何类实例。如果你是一位 Java 或 C++程序员,这种类型的数据相当于在一个变量声明前加上 static 关键字。
静态成员通常仅用来跟踪与类相关的值。
class Attri(): arrtitest = "class attribute test" if __name__ == '__main__': print(Attri.arrtitest) D:PythonPython35python.exe D:/PycharmProjects/pythonOO/class_attribute.py class attribute test Process finished with exit code 0
查看类的属性
print(dir(Second)) ['__class__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__',
'__getattribute__', '__gt__', '__hash__', '__init__', '__le__', '__lt__', '__module__', '__ne__',
'__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__',
'__subclasshook__', '__weakref__', 'raiseup', 'raiseupWith'] print(Second.__dict__) {'raiseupWith': <function Second.raiseupWith at 0x0000015AEFE46598>,
'__module__': '__main__', '__doc__': None, '__init__': <function Second.__init__ at 0x0000015AEFE46510>}
特殊的类属性
print(Second.__name__) Second print(Second.__base__) <class '__main__.First'> print(Second.__module__) __main__ print(Second.__class__) <class 'type'>
6. 示例
如果说类是一种数据结构定义类型,那么实例则声明了一个这种类型的变量。换言之,实例是有生命的类。就像设计完一张蓝图后,就是设法让它成为现实。实例是那些主要用在运行期时的对象,类被实例化得到实例,该实例的类型就是这个被实例化的类。
__init__() ,可使用默认参数,__init__()应当返回 None
__new__() :【需要继续学下】这是因为__new__()必须返回一个合法的实例,这样解释器在调用__init__()时,就可以把这个实例作为 self 传给它。调用父类的__new__()来创建对象,正像其它语言中使用 new 关键字一样
__del__() :特殊解构器(destructor) ,由于 Python 具有垃圾对象回收机制(靠引用计数),这个函数要直到该实例对象所有的引用都被清除掉后才会执行。
7. 实例属性
实例仅拥有数据属性。是与某个类的实例相关联的数据值,并且可以通过句点属性标识法来访问。这些值独立于其它实例或类。当一个实例被释放后,它的属性同时也被清除了。
设置实例的属性可以在实例创建后任意时间进行,也可以在能够访问实例的代码中进行
能够在“运行时”创建实例属性,是 Python 类的优秀特性之一
特殊实例属性:
I.__class__ 实例化 I 的类
I.__dict__ I 的属性
类和实例都是名字空间。类是类属性的名字空间,实例则是实例属性的。
class C(): ver = 1.2 c = C() print (C.ver) print (c.ver) c.ver = 1.3 print("---------------") print (C.ver) print (c.ver) print("---------------") C.ver = 1.5 print (C.ver) print (c.ver) D:PythonPython35python.exe D:/PycharmProjects/pythonOO/classAttributTest.py 1.2 1.2 --------------- 1.2 1.3 --------------- 1.5 1.3 Process finished with exit code 0
8 静态方法 类方法
类方法隐含的参数为类本身cls。
静态方法无隐含参数,主要为了类实例也可以直接调用静态方法
旧式类
对于类方法而言,需要类而不是实例作为第一个参数,它是由解释器传给方法。类不需要特别地命名, 类似 self,不过很多人使用 cls 作为变量名字。
class TStaticMethod: def foo(): print('calling static method foo()') foo = staticmethod(foo) class TStaticMethod2: def foo(cls): print('calling static method foo()2') foo = classmethod(foo) TStaticMethod.foo() TStaticMethod2.foo() D:PythonPython35python.exe "D:Program Files (x86)JetBrainsPyCharm Community Edition 2016.3.2helperspycharmutrunner.py" D:PycharmProjectspythonOOstaticMethod1.py true Testing started at 21:57 ... calling static method foo() calling static method foo()2 Process finished with exit code 0 Empty test suite.
新式,使用注解 @staticmethod,@classmethod
class TestStaticMethod: @staticmethod def foo(): print 'calling static method foo()' class TestClassMethod: @classmethod def foo(cls): print 'calling class method foo()' print 'foo() is part of class:', cls.__name__