Python属性和描述符

时间:2016-11-07 11:42:32

标签: python python-3.x descriptor python-descriptors

我一直在阅读Descriptor HowTo Guide中的描述符,我对这句话感到困惑:

  

如果实例的字典具有与数据描述符同名的条目,则数据描述符优先。

字典如何包含两个具有相同名称的项目(普通条目和数据描述符)?或者描述符的属性是否未存储在Process: com.astech.android.webxbettingsystem, PID: 17476 java.lang.RuntimeException: Error receiving broadcast Intent { act=android.intent.action.DOWNLOAD_COMPLETE flg=0x10 pkg=com.astech.android.webxbettingsystem (has extras) } in com.astech.android.webxbettingsystem.ui.activity.CheckAppUpdateActivity$1@1282c32 at android.app.LoadedApk$ReceiverDispatcher$Args.run(LoadedApk.java:932) at android.os.Handler.handleCallback(Handler.java:815) at android.os.Handler.dispatchMessage(Handler.java:104) at android.os.Looper.loop(Looper.java:207) at android.app.ActivityThread.main(ActivityThread.java:5737) at java.lang.reflect.Method.invoke(Native Method) at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:789) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:679) Caused by: android.content.ActivityNotFoundException: No Activity found to handle Intent { act=android.intent.action.VIEW dat=content://downloads/my_downloads/572 typ=application/vnd.android.package-archive flg=0x10000000 } at android.app.Instrumentation.checkStartActivityResult(Instrumentation.java:1809) at android.app.Instrumentation.execStartActivity(Instrumentation.java:1523) at android.app.Activity.startActivityForResult(Activity.java:3968) at android.support.v4.app.BaseFragmentActivityJB.startActivityForResult(BaseFragmentActivityJB.java:48) at android.support.v4.app.FragmentActivity.startActivityForResult(FragmentActivity.java:75) at android.app.Activity.startActivityForResult(Activity.java:3920) at android.support.v4.app.FragmentActivity.startActivityForResult(FragmentActivity.java:856) at android.app.Activity.startActivity(Activity.java:4259) at android.app.Activity.startActivity(Activity.java:4227) at com.astech.android.webxbettingsystem.ui.activity.CheckAppUpdateActivity$1.onReceive(CheckAppUpdateActivity.java:55) at android.app.LoadedApk$ReceiverDispatcher$Args.run(LoadedApk.java:922) at android.os.Handler.handleCallback(Handler.java:815)  at android.os.Handler.dispatchMessage(Handler.java:104)  at android.os.Looper.loop(Looper.java:207)  at android.app.ActivityThread.main(ActivityThread.java:5737)  at java.lang.reflect.Method.invoke(Native Method)  at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:789)  at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:679) 

2 个答案:

答案 0 :(得分:3)

数据描述符存在于命名空间中,而实例属性存在于实例命名空间中(因此instance.__dict__)。这是两个单独的词典,因此这里没有冲突。

因此,对于实例foo上名称bar的任何给定属性查找,Python也会查看它的类(type(bar),下面名为C),以下顺序:

    查找
  1. C.foo。如果它是数据描述符,则查找结束。返回C.foo.__get__(bar, C)。否则,Python会将此结果存储在第3步中(没有必要再查看两次)。

  2. 如果C.foo不存在或是常规属性,则Python会查找bar.__dict__['foo']。如果存在,则返回。请注意,如果C.foo是数据描述符,则永远不会到达此部分!

  3. 如果bar.__dict__['foo']不存在,但C.foo存在,则使用C.foo。如果C.foo是(非数据)描述符,则返回C.foo.__get__(bar, C)

  4. (注意C.foo实际上是C.__dict__['foo'],但为了简单起见,我忽略了上面类中的描述符访问。)

    也许一个具体的例子有帮助;这里有两个描述符,一个是数据描述符(有__set__方法),另一个是数据描述符:

    >>> class DataDesc(object):
    ...     def __get__(self, inst, type_):
    ...         print('Accessed the data descriptor')
    ...         return 'datadesc value'
    ...     def __set__(self, inst, value):
    ...         pass   # just here to make this a data descriptor
    ...
    >>> class OtherDesc(object):
    ...     def __get__(self, inst, type_):
    ...         print('Accessed the other, non-data descriptor')
    ...         return 'otherdesc value'
    ...
    >>> class C(object):
    ...     def __init__(self):
    ...         # set two instance attributes, direct access to not
    ...         # trigger descriptors
    ...         self.__dict__.update({
    ...             'datadesc': 'instance value for datadesc',
    ...             'otherdesc': 'instance value for otherdesc',
    ...         })
    ...     datadesc = DataDesc()
    ...     otherdesc = OtherDesc()
    ...
    >>> bar = C()
    >>> bar.otherdesc  # non-data descriptor, the instance wins
    'instance value for otherdesc'
    >>> bar.datadesc  # data descriptor, the descriptor wins
    Accessed the data descriptor
    'datadesc value'
    

答案 1 :(得分:1)

请考虑以下代码段:

{{1}}

此代码打印2,因为数据描述符(在类上定义)优先于实例字典。