社区所有版块导航
Python
python开源   Django   Python   DjangoApp   pycharm  
DATA
docker   Elasticsearch  
aigc
aigc   chatgpt  
WEB开发
linux   MongoDB   Redis   DATABASE   NGINX   其他Web框架   web工具   zookeeper   tornado   NoSql   Bootstrap   js   peewee   Git   bottle   IE   MQ   Jquery  
机器学习
机器学习算法  
Python88.com
反馈   公告   社区推广  
产品
短视频  
印度
印度  
Py学习  »  Python

[精华] Python OOP 常见疑难点汇总(1).基础

BeginMan • 10 年前 • 5815 次点击  

Python面向对象常见疑难点汇总{文章同步在http://beginman.sinaapp.com/}, 终于闲下来了,有点空回顾基础知识。

No1.公有私有属性

python oop无public 和private,对类的私有属性的处理通过__

class P():
    a = 100      # public
    __a = 200    # private
    def func(self):
        print 'Public function'
        print self.a
        print self.__a

    def __pfunc(self):
        print 'Private function'
        print self.a
        print self.__a

p = P()
print p.a
print p.__a      #err
print p.func()
print p.__pfunc()  #err

NO2.self的哲学

self非关键字,而是一个参数对象的代表,像this一样,代表实例对象本身。调用实例方法,会隐式传实递实例对象。

>>> class P():
...     def func(self):
...         print self
...         
...     
... 
>>> p = P()  # 实例化
>>> p.func()  # 调用实例方法,此时隐式传实递实例p对象
<__main__.P instance at 0xb69282cc>

No3.新式类VS经典类

新式类:就是所有类都必须继承的类,如果什么都不想继承,就继承到object类。 经典类:没有父类

1.递归问题

http://zxn990.blog.51cto.com/4253193/1285599

2.调用父类构造器

http://jianshu.io/p/2ZxRsn

下面来自http://stackoverflow.com/questions/54867/old-style-and-new-style-classes-in-python

Up to Python 2.1, old-style classes were the only flavour available to the user. The concept of (old-style) class is unrelated(无关的) to the concept of type: if x is an instance of an old-style class, then x.class designates the class of x, but type(x) is always <type 'instance'>. This reflects the fact that all old-style instances, independently of their class, are implemented with a single built-in type, called instance.

New-style classes were introduced in Python 2.2 to unify classes and types. A new-style class neither more nor less than a user-defined type. If x is an instance of a new-style class, then type(x) is the same as x.class.

The major motivation for introducing new-style classes is to provide a unified object model with a full meta-model. It also has a number of immediate benefits, like the ability to subclass(亚纲) most built-in types, or the introduction of "descriptors(描述符号)", which enable computed properties.

For compatibility reasons, classes are still old-style by default. New-style classes are created by specifying another new-style class (i.e. a type) as a parent class, or the "top-level type" object if no other parent is needed. The behaviour of new-style classes differs from that of old-style classes in a number of important details in addition to what type returns. Some of these changes are fundamental to the new object model, like the way special methods are invoked. Others are "fixes" that could not be implemented before for compatibility concerns, like the method resolution order in case of multiple inheritance.

Python 3 only has new-style classes. No matter if you subclass from object or not, classes are new-style in Python 3. It is however recommended that you still subclass from object.

>>> p = P2()               # 经典类
>>> p.__class__         
<class __main__.P2 at 0xb68bd1dc>
>>> type(p)
<type 'instance'>

>>> pp = P()               # 新式类
>>> pp.__class__
<class '__main__.P'>
>>> type(pp)
<class '__main__.P'>

No4.类方法VS实例方法VS静态方法

类方法:classmethod修饰,第一个参数cls,类与实例共享。

实例方法:无修饰,第一个参数self,实例所有

静态方法:staticmethod修饰,无需参数,类与实例共享。无法访问类属性、实例属性,相当于一个相对独立的方法,跟类其实没什么关系,换个角度来讲,其实就是放在一个类的作用域里的函数而已。静态方法中引用类属性的话,必须通过类对象来引用。

class P(object):
    tip = 'Persion tips'  # 类属性,类及类成员共享
    @classmethod
    def clsFunc(cls):
        """类方法共享"""
        return 'Welcome:' + cls.tip
    def insFunc(self):
        """实例方法"""
        return self.__class__
    @staticmethod
    def staFunc():
        """静态方法"""
        return P.tip

p = P()
print P.tip
print p.tip
print p.insFunc()
p.age = 20   # 实例属性无需在类中显示定义
print p.age
print p.clsFunc()  # 类方法
print p.clsFunc()  
print p.staFunc() # 静态方法实例与类共享
print p.staFunc()

NO5.init VS new

首先看这段代码,代码参考Python's use of new and init?

class P(object):
    _dict = dict()
    def __new__(cls):
        if 'key' in P._dict:
            print "EXISTS"
            #return P._dict['key']    # 返回实例对象
            return P._dict            # 返回不合法的对象
        else:
            print 'NEW'
            return super(P, cls).__new__(cls)  # 返回实例对象

    def __init__(self):
        print 'INIT..'
        P._dict['key'] = self
        print " "


p1 = P()
p2 = P()
p3 = P()

# 输出结果
NEW
INIT..

EXISTS
EXISTS

# 如果把上面的注释取消,变成:return P._dict['key'] 则输出结果如下:


    

NEW
INIT..

EXISTS
INIT..

EXISTS
INIT..

看出点端倪了么。。

__new__():静态方法,cls作为第一个参数,控制创造一个新实例

__init__():实例方法,self作为第一个参数,控制初始化一个实例

在Python OOP中,__new__()相比__init__()更像一个构造器,__new__()是一个静态方法,必须返回一个合法的实例,这样解释器在调用init()之前把这个实例作为self传递过去

__init__()实例初始化,它返回None,它的工作就是在实例被创建(new())后初始化它。

>>> class P(object):
...     def __init__(self):
...         print 'ok'
...     def __new__(cls):
...         print 'new'
...         
...     
... 
>>> p = P()
new
>>> class P(object):
...     def __init__(self):
...         print 'ok'
...         
...     def __new__(cls):
...         print 'new'
...         return super(P, cls).__new__(cls)
...     
... 
>>> p = P()
new
ok

NO6.特殊的实例属性VS特殊的类属性

dir()相关知识移步这里http://sebug.net/paper/python/ch08s06.html.

特殊实例属性:__dict__,__init__,__class__,如:

>>> p.__class__
<class __main__.P at 0xb692d05c>
>>> p.__doc__
>>> p.__init__
<bound method P.__init__ of <__main__.P instance at 0xb6936bac>>
>>> p.__module__
'__main__'
>>> p.__new__
<bound method P.__new__ of <__main__.P instance at 0xb6936bac>>
>>> p.__dict__
{}
>>> p.age = 100
>>> p.__dict__
{'age': 100}
>>> dir(p)
['__doc__', '__init__', '__module__', '__new__', 'age']

特殊类属性:C.__name__:类名, C.__bases__ or(__base__):父类,C.__dict__:类属性, C.__module__:定义类所在的model, C.__class__:实例C对应的类。

一般这些特殊的东西用的较少,这里展示下且当记忆。

NO7.理解super()

super主要为了不显示的引用基类的东西,主要的优势体现在多重继承上如 class (A,B)等,使用super能够智能的帮助我们调用基类。

  1. super并不是一个函数,是一个类名,形如super(B, self)事实上调用了super类的初始化函数,产生了一个super对象;
  2. super类的初始化函数并没有做什么特殊的操作,只是简单记录了类类型和具体实例;
  3. super(B, self).func的调用并不是用于调用当前类的父类的func函数;
  4. Python的多继承类是通过mro的方式来保证各个父类的函数被逐一调用,而且保证每个父类函数只调用一次(如果每个类都使用super);
  5. 混用super类和非绑定的函数是一个危险行为,这可能导致应该调用的父类函数没有调用或者一个父类函数被调用多次。

关于Python super的解释参考这里python super().

这里有个误区就是:

super( BasicElement, self ).__init__()
super( BasicElement, self ).__init__(self)

实例如下:

>>> class A(object):
...     def __init__(self):
...         print 'AAAAAA'
...         
...     
... 
>>> class B(A):
...     def __init__(self):
...         super(B, self).__init__()
...         
...     
... 
>>> b = B()
AAAAAA

>>> class B(A):
...     def __init__(self):
...         super(B, self).__init__(self)
...         
...     
... 
>>> b = B()
Traceback (most recent call last):
  File "<input>", line 1, in <module>
  File "<input>", line 3, in __init__
TypeError: __init__() takes exactly 1 argument (2 given)

>>> class A(object):
...     def __init__(self, args):
...         print 'AAAAAAAAAAA', args
...         
...     
... 
>>> class B(A):
...     def __init__(self):
...         super(B, self).__init__('Man')
...         
...     
... 
>>> b = B()
AAAAAAAAAAA Man

看出super(B, self).__init__("sss") 向基类传参。在Python3中,可以直接写super().init() 取代 super(B, self).init()

Python社区是高质量的Python/Django开发社区
本文地址:http://www.python88.com/topic/541
 
5815 次点击  
文章 [ 3 ]  |  最新文章 10 年前