• python面向对象编程


    python中。面向对象编程主要有两个主题,就是类和类实例。

    1、类

    新式类——


    class ClassName(bases):
    	'ClassName class doc string'
    	class_suite

    经典类——

    class ClassName:
    	'ClassName class doc string'
    	class_suite

    keyword是class,紧接着是一个类名,随后是定义类的类体代码。

    新式类和经典类声明的最大不同在于,全部新式类必须继承至少一个父类,參数bases能够是一个或多个用于继承的父类,即单继承或多重继承。而经典类能够不指定父类。

    object类是全部类的父类。类通常在一个模块的顶层进行定义。

    方法——

    class ClassName(bases):
    	'ClassName class doc string'
    	def function(self[, args]):
    		pass

    定义方法就是在类定义中使用keyworddef。这种方法仅仅能被类实例所调用。

    方法的第一个參数是selfkeyword。类似于C++thiskeyword,self代表实例对象本身。通过类实例调用方法时解释器会自己主动传入self參数,而不须要我们自己传递self进来。

    python不支持C++那样的纯虚函数或者抽象方法,作为替代方法,能够简单地在父类方法中引发NotImplementedError异常来获得类似的效果。

    静态方法与类方法——

    staticmethod()classmethod()是内建的静态方法、类方法装饰器,两者都不须要self參数。后者须要类作为第一个參数。也是由解释器自己主动传入的。

    __init__()方法——

    class ChildClass(ParentClass):
    	' ChildClass class doc string'
    	def __init__(self[, args]):
    		ParentClass.__init__(self[, args])
    		pass

    __init__()方法类似于C++的构造器,实例化时会首先调用这个函数,作一些初始化工作。子类可能会自己主动调用父类的这种方法,子类重写了这种方法后,父类的就不会调用了,须要我们在子类中显式地掉用父类的方法,并且要传入self,这是由于我们不是在父类的实例中调用方法。而是在一个子类实例中调用的。这种方法是未绑定的。返回非None的不论什么其他对象都会导致TpyeError异常。

    __new__()方法——

    __new__()方法事实上更像一个构造器。由于它必须返回一个合法的实例。

    __del__()方法——

    __del__()方法像个析构器,然而因为python具有靠引用计数的垃圾对象回收机制,这个函数要直到该实例对象全部的引用都被清除掉后才会运行。

    del降低的是引用计数,不一定会调用这个函数。

    假设继承自父类,不要忘记首先调用父类的这个函数。

    特殊方法——

    上面列举了三个特殊方法,事实上python还提供了很多其他的特殊方法,以双下划线開始及结尾。这些特殊方法是python中用来扩充类的强有力的方式,能够模拟标准类型。或者重载操作符,如同C++中的操作符重载一样,这些内容后面会有介绍。

    类属性——

    class C(object):
    	'C class doc string'
    	foo = 100

    类属性是与类对象绑定的,不依赖于不论什么类实例,类似于C++statickeyword。

    查看类属性可通过内建函数dir()或者訪问类的字典属性__dict__,后者等同于内建函数vars()接收类对象作为參数的效果。类属性訪问可通过类名或者类实例完毕。但类属性的改动仅仅能通过类名进行(假设从实例中訪问类属性。恰好类属性是个字典,这时类属性是能够通过实例来改动的)。所以,改动类属性,须要使用类名而不是实例。

    特殊类属性——

    对不论什么类C。都有例如以下特殊类属性

    C.__name__

    C.__doc__

    C.__bases__

    C.__dict__

    C.__module__

    C.__class__

    2、实例

    实例化——

    myObj = Classname()

    实例化像调用函数那样,通过一对圆括号来完毕。

    实例属性——

    myObj.name = ‘Blithe’
    myObj.age = ‘20’

    实例属性不同于类属性。实例属性是这个实例的而不属于类,实例属性能够在“执行时”创建,当一个实例被释放后。它的属性同一时候也被清除了。构造器是最早能够设置实例属性的地方,由于它是实例创建后第一个被调用的地方。

    查看实例属性能够像查看类属性一样,使用相同的方法。

    特殊实例属性——

    对于随意对象I。都仅有例如以下两个特殊实例属性

    I.__class__

    I.__dict__

    3、类扩展

    类扩展有两种方式。一种是类组合,即类属性的类型为某个类对象,还有一种是类继承。在上面的介绍中,假设子类重写了父类的某个方法,在子类中调用父类的这种方法时,要通过父类名调用,写入父类名非最佳选择,一个好用的方法是使用super()。例如以下:

    class Parent(object):
    	def foo(self):
    		pass
    class Child(Parent):
    	def foo(self):
    		super(Child, self).foo()
    		pass

    python2.2以后的版本号中,类型和类统一了起来,这种话,我们就能从标准类型中派生子类,常见使用方法是重写基类的方法。

    多重继承时,经典类和新式类的方法搜索顺序MRO不同,前者使用深度优先算法,而后者继承自object,新的菱形类继承结构出现了,需使用广度优先算法。

    4、实用的内建函数

    issubclass(sub,sup):推断sub类是否是sup类的子类或者子孙类,sup能够是sub自身,还能够是很多类组成的元组。

    isinstance(obj1,obj2):推断obj1是否是obj2的实例,obj2能够是元组。

    hasattr(obj,'attr'):推断obj是否包括attr属性。

    getattr(obj,'attr'[,value]):获取obj中的attr属性,没有这个属性时会触发AttributeError异常,可设置属性的默认值value

    setattr(obj,'attr',value):设置obj中的attr属性。

    delattr(obj,'attr'):删除obj中的attr属性。

    dir([obj]):显示obj的属性,參数能够是类、实例、模块。不带參数时显示调用者的局部变量。

    super(type[,obj]):前面介绍过。这个函数的目的就是帮助找出父类。对于每一个定义的类,都有一个名为__mro__的属性,它是一个元组,依照它们被搜索时所顺序。列出了备搜索的类。

    vars([obj]):与内建函数dir()相似,仅仅是这个函数的obj必须有一个__dict__属性,否则会触发TypeError异常。

    5、定制类

    前面提到了特殊方法。我们能够使用特殊方法来定制类,扩展类功能。

    以下是一个简单的样例。RoundFloat类用来对一个float数值进行四舍五入,保留两位小数。__init__()中的assert推断构造器输入參数必须是一个float数值。否则会触发异常,异常參数是一个自己定义的字符串,__str__()是用来支持print语句的,__repr__()__str__()的别名,支持真正的字符串对象显示出来。

    class RoundFloat(object): 
    	def __init__(self, val): 
    		assert isinstance(val, float),  
    		"value must be a float!" 
    		self.value = round(val, 2) 
    
    	def __str__(self): 
    		return "%.2f" %self.value 
    
    	__repr__ = __str__

    6、私有化

    默认情况下。属性在python中都是public的。

    python的类并没有像C++那样的private等keyword用于属性可见性标识,但有其他的方法。私有元素以双下划线开头,直接訪问是不同意的,比如类C中的self.__age元素,訪问时必须是self._C__age。元素前加单个下划线和类名。

    双下划线的还有一个优点是保护变量不与父类名字空间相冲突。

    7、包装

    包装。意思是对一个已存在的对象进行包装。添加新的、删除不要的、或者改动其他已存在的功能,它的实例拥有标准类型的核心行为,同一时候又表现出与原类不同的行为。

    授权是包装的一个特性,授权的过程,即是全部更新的功能都是由新类的某部分来处理。但已存在的功能就授权给对象的默认属性。

    实现授权的关键点就是覆盖__getattr__()方法,在代码中包括一个对getattr()内建函数的调用。

    特别地,调用getattr()以得到默认对象属性并返回它。以便訪问或调用。

    特殊方法__getattr__()的工作方式是,当搜索一个属性时,不论什么局部对象首先被找到。假设搜索失败了。则__getattr__()会被调用。然后调用getattr()得到不论什么一个对象的默认行为。

    8、新式类

    与经典类相比,新式类统一了类型和类,最重要的特性是可以子类化python数据类型。只是很多内建函数都转化成为了工厂函数,当这些函数被调用时,实际上是对对应的类型进行实例化。

    __slots__类属性——

    __dict__字典属性能够跟踪全部的实例属性,但会占领大量内存。为内存上的考虑,能够使用__slots__类属性替代字典属性。__slots__能够是一个列表、元组或可迭代对象。也能够是标识实例能拥有的唯一属性的简单字符串。不论什么试图创建一个其名不在__slots__中的名字的实例属性都将导致AttributeError异常。带__slots__属性的类定义不会存在__dict__

    __getattribute__()特殊方法——

    前面提到的__getattr__()特殊方法仅当属性不能在__dict__中找到时才被调用,包装授权中用到了这个函数,__getattribute__()类似前者,不同之处在于当属性被訪问时,它就一直能够被调用。而不局限与不能找到的情况。假设类同一时候定义了这两个方法。除非明白从后者调用或引发AttributeError异常,否则前者不会被调用。

    描写叙述符——

    描写叙述符python新式类的关键点之中的一个,它为对象属性提供了强大的API,能够觉得描写叙述符是表示对象属性的一个代理。当须要属性时。常规方式是通过句点訪问,假设有描写叙述符的话也能够用来訪问属性。描写叙述符实际上能够是不论什么类。这样的类至少实现了三个属性操作的特殊方法__get__()__set__()__delete__()中的一个。

    整个描写叙述符系统的核心是__getattribute__()。它的实现方式非常特别。有一定的优先级顺序。从高到低依次是类属性、数据描写叙述符、实例属性、非数据描写叙述符及默认的__getattr__()

    静态方法、类方法、属性,甚至全部的函数都是描写叙述符。

    属性是一种实用的特殊类型的描写叙述符,property()内建函数原型例如以下:

    property(fget=None, fset=None, fdel=None, doc=None)

    以下是property的一个简单使用方法:

    class C(object): 
    	def getx(self): return self._x 
    	def setx(self, value): self._x = value 
    	def delx(self): del self._x 
    	x = property(getx, setx, delx, "I'm the 'x' property.")

    property还可用作装饰器:

    class C(object): 
    	@property 
    	def x(self): return self._x 
    	@x.setter 
    	def x(self, value): self._x = value 
    	@x.deleter 
    	def x(self): del self._x 

    元类——

    元类用来定义某些类是怎样被创建的。拥有创建类的控制权,相关的类属性是__metaclass__,传统类(找不到__metaclass__的元类为types.ClassType。元类通常传递三个參数到构造器,各自是类名、从基类继承数据的元组和属性字典。

    以下是元类应用的一个样例。它仅仅是在用元类创建一个类时,显示时间标签

    #!/usr/bin/env python 
    
    from time import ctime 
    
    print '*** Welcome to Metaclasses!' 
    print '	Metaclass declaration first.' 
    
    class MetaC(type): 
    	def __init__(cls, name, bases, attrd): 
    		super(MetaC, cls).__init__(name, bases, attrd) 
    		print '*** Created class %r at: %s' %(name, ctime()) 
    
    print '	Class "Foo" declaration next.' 
    
    class Foo(object): 
    	__metaclass__ = MetaC 
    	def __init__(self): 
    		print '*** Instantiated class %r at: %s' %(self.__class__.__name__, ctime()) 
    
    print '	Class "Foo" instantiation next.' 
    f = Foo() 
    print '	DONE'

    以下是log输出

    *** Welcome to Metaclasses! 
    	Metaclass declaration first. 
    	Class "Foo" declaration next. 
    *** Created class 'Foo' at: Thu Jun  4 10:03:06 2015 
    	Class "Foo" instantiation next. 
    *** Instantiated class 'Foo' at: Thu Jun  4 10:03:06 2015 
    	DONE 

    以下是元类应用的一个略微复杂的样例,要求新创建的类重写__str__()__repr__()两个方法,假设没有的话,前者触发异常,后者引起警告。

    #!/usr/bin/env python 
    
    from warnings import warn 
    
    class ReqStrSugRepr(type): 
    	def __init__(cls, name, bases, attrd): 
    		print '*** Defined ReqStrSugRepr (meta)class
    ' 
    
    		super(ReqStrSugRepr, cls).__init__(name, bases, attrd) 
    
    		if '__str__' not in attrd: 
    			aerror = 'Class %r requires overriding of __str__()' %name 
    			raise TypeError(aerror) 
    
    		if '__repr__' not in attrd: 
    			awarn = 'Class %r suggests overriding of __repr__()
    ' %name 
    			warn(awarn, stacklevel = 3) 
    
    		print '*** Created %r class
    ' %name 
    
    
    class Foo(object): 
    	__metaclass__ = ReqStrSugRepr 
    
    	def __str__(self): 
    		return 'Instance of class:', self.__class__.__name__ 
    
    	def __repr__(self): 
    		return self.__class__.__name__ 
     
    
    class Bar(object): 
    	__metaclass__ = ReqStrSugRepr 
    
    	def __str__(self): 
    		return 'Instance of class:', self.__class__,__name__ 
    
    
    class FooBar(object): 
    	__metaclass__ = ReqStrSugRepr

    以下是log输出

    *** Defined ReqStrSugRepr (meta)class 
    
    *** Created 'Foo' class 
    
    *** Defined ReqStrSugRepr (meta)class 
    
    sys:1: UserWarning: Class 'Bar' suggests overriding of __repr__() 
    
    *** Created 'Bar' class 
    
    *** Defined ReqStrSugRepr (meta)class 
    
    Traceback (most recent call last): 
      File "./metaCEx2.py", line 39, in <module> 
        class FooBar(object): 
      File "./metaCEx2.py", line 13, in __init__ 
        raise TypeError(aerror) 
    TypeError: Class 'FooBar' requires overriding of __str__() 

    9、几个模块

    UserList:提供一个列表对象的封装类。

    UserDict:提供一个字典对象的封装类。

    UserString:提供一个字符串对象的封装类,它又包含一个MutableString子类。

    types:定义全部python对象的类型在标准python解释器中的名字。

    operator:标准操作符的函数接口。


  • 相关阅读:
    POJ 3321:Apple Tree + HDU 3887:Counting Offspring(DFS序+树状数组)
    BZOJ 1026:windy数(数位DP)
    POJ 3087 Shuffle'm Up
    POJ 1835 宇航员
    差分约束系统
    POJ
    2016 百度之星初赛 Gym Class(优先队列+拓扑排序)
    HDU 4786 Fibonacci Tree
    Codeforces 691D Swaps in Permutation
    FZU 2195 检查站点
  • 原文地址:https://www.cnblogs.com/gavanwanggw/p/6731571.html
Copyright © 2020-2023  润新知