سؤال

(عندما أقول "عنوان الكائن" ، أعني السلسلة التي تكتبها في Python للوصول إلى كائن. على سبيل المثال 'life.State.step'. في معظم الأوقات ، ستكون جميع الكائنات قبل النقطة الأخيرة هي الحزم/الوحدات النمطية ، ولكن في بعض الحالات يمكن أن تكون فئات أو كائنات أخرى.)

في مشروع بيثون غالبًا ما أحتاج إلى اللعب مع عناوين الكائنات. بعض المهام التي يجب أن أفعلها:

  1. بالنظر إلى كائن ، احصل على عنوانه.
  2. بالنظر إلى عنوان ، احصل على الكائن ، واستيراد أي وحدات مطلوبة في الطريق.
  3. اختصر عنوان الكائن من خلال التخلص من الوحدات الوسيطة الزائدة عن الحاجة. (فمثلا، 'life.life.State.step' قد يكون العنوان الرسمي لكائن ، ولكن إذا 'life.State.step' نقاط في نفس الكائن ، أريد استخدامه بدلاً من ذلك لأنه أقصر.)
  4. قم بتقصير عنوان الكائن عن طريق "تأصيل" وحدة محددة. (فمثلا، 'garlicsim_lib.simpacks.prisoner.prisoner.State.step' قد يكون العنوان الرسمي لكائن ، لكنني أفترض أن المستخدم يعرف مكان prisoner الحزمة هي ، لذلك أريد استخدام 'prisoner.prisoner.State.step' كعنوان.)

هل هناك وحدة/إطار يتولى أشياء من هذا القبيل؟ لقد كتبت بعض وحدات الأداة المساعدة للقيام بهذه الأشياء ، ولكن إذا كان شخص ما قد كتب بالفعل وحدة نمطية أكثر نضجًا تقوم بذلك ، فأنا أفضل استخدام ذلك.

ملاحظة واحدة: من فضلك ، لا تحاول أن تريني تنفيذًا سريعًا لهذه الأشياء. إنه أكثر تعقيدًا مما يبدو ، هناك الكثير من gotchas ، وربما يفشل أي رمز سريع n-dirty في العديد من الحالات المهمة. هذا النوع من المهام تدعو إلى الكود الذي تم اختباره في المعركة.

تحديث: عندما أقول "كائن" ، أقصد في الغالب الفئات والوحدات النمطية والوظائف والأساليب وأشياء مثل هذه. آسف لعدم توضيح هذا من قبل.

هل كانت مفيدة؟

المحلول 2

لقد أصدرت address_tools الوحدة التي تفعل بالضبط ما طلبت.

هنا هو الرمز. ها هي الاختبارات.

إنه جزء من Garlicsim, ، حتى تتمكن من استخدامه بواسطة تثبيت garlicsim والقيام from garlicsim.general_misc import address_tools. وظائفها الرئيسية describe و resolve, ، والتي هي موازية ل repr و eval. تشرح Docstrings كل شيء عن كيفية عمل هذه الوظائف.

حتى أن هناك نسخة بيثون 3 على بيثون 3 شوكة من Garlicsim. قم بتثبيته إذا كنت تريد استخدامها address_tools على كود بيثون 3.

نصائح أخرى

إجابة قصيرة: لا. ما تريده مستحيل.

الجواب الطويل هو أن ما تفكر فيه باعتباره "عنوان" كائن ما ليس سوى شيء. life.State.step هي مجرد إحدى الطرق للحصول على إشارة إلى الكائن في هذا الوقت بالذات. يمكن أن يمنحك نفس "العنوان" عند نقطة لاحقة كائنًا مختلفًا ، أو قد يكون خطأ. ما هو أكثر من ذلك ، هذا "العنوان" لك يعتمد على السياق. في life.State.step, ، الكائن النهائي لا يعتمد فقط على ماذا life.State و life.State.step هم ، ولكن ما هو الكائن الاسم life يشير إلى مساحة الاسم.

إجابات محددة لطلباتك:

  1. الكائن النهائي له بأي حال من الأحوال لمعرفة كيفية إحالتك إليها ، وليس لديها أي رمز تعطيه الكائن إليه. "العنوان" ليس اسمًا ، فهو ليس مرتبطًا بالكائن ، إنه مجرد تعبير بيثون تعسفي ينتج عنه مرجع كائن (كما تفعل جميع التعبيرات.) يمكنك فقط جعل هذا العمل ، بالكاد, ، مع وجود كائنات محددة من غير المتوقع أن تتحرك ، مثل الفئات والوحدات النمطية. ومع ذلك ، هذه الأشياء يستطيع تحرك ، وكثيرا فعل تحرك ، لذلك من المحتمل أن تنكسر ما تحاول.

  2. كما ذكرنا ، يعتمد "العنوان" على أشياء كثيرة ، لكن هذا الجزء سهل إلى حد ما: __import__() و getattr() يمكن أن يعطيك هذه الأشياء. ومع ذلك ، سيكونون هشين للغاية ، خاصة عندما يكون هناك مشاركة أكثر من مجرد الوصول إلى السمة. لا يمكن إلا أن تعمل عن بُعد مع الأشياء الموجودة في الوحدات النمطية.

  3. "تقصير" يتطلب الاسم فحص كل اسم ممكن, بمعنى جميع الوحدات النمطية وجميع الأسماء المحلية ، و كل سماتها, ، بالتسجيل. ستكون عملية بطيئة للغاية وتستغرق وقتًا طويلاً ، وهشة للغاية في مواجهة أي شيء مع أ __getattr__ أو __getattribute__ الطريقة ، أو مع الخصائص التي تفعل أكثر من إرجاع القيمة.

  4. هو نفس الشيء مثل 3.

للنقطتين 3 و 4 ، أعتقد أنك تبحث عن مرافق مثل

from life import life  # life represents life.life
from garlicsim_lib.simpacks import prisoner

ومع ذلك ، لا ينصح هذا ، لأنه يجعل من الصعب عليك أو الأشخاص الذين قرأوا الكود الخاص بك لمعرفة ماذا بسرعة prisoner يمثل (حيث تأتي الوحدة النمطية؟ عليك أن تنظر إلى بداية الكود للحصول على هذه المعلومات).

للنقطة 1 ، يمكنك القيام:

from uncertainties import UFloat

print UFloat.__module__  # prints 'uncertainties'

import sys
module_of_UFloat = sys.modules[UFloat.__module__]

للنقطة 2 ، بالنظر إلى السلسلة "garlicsim_lib.simpacks.prisoner" ، يمكنك الحصول على الكائن الذي يشير إليه مع:

obj = eval('garlicsim_lib.simpacks.prisoner')

هذا يفترض أنك قمت باستيراد الوحدة مع

import garlicsim_lib  # or garlicsim_lib.simpacks

إذا كنت تريد أن يكون هذا تلقائيًا ، فيمكنك فعل شيء على غرار

import imp

module_name = address_string.split('.', 1)[0]
mod_info = imp.find_module(module_name)
try:
    imp.load_module(module_name, *mod_info)
finally:
    # Proper closing of the module file:
    if mod_info[0] is not None:
        mod_info[0].close()

هذا يعمل فقط في أبسط الحالات (garlicsim_lib.simpacks يجب أن تكون متاحة في garlicsim_lib, ، على سبيل المثال).

ترميز الأشياء بهذه الطريقة ، مع ذلك ، غير عادي للغاية.

Twisted لديه #2 كما ملتوية/python/respect.py. تحتاج إلى شيء مثله لإنشاء نظام تكوين قائم على السلسلة ، مثل تكوين urls.py الخاص بـ Django.

ألقِ نظرة على الكود وسجل التحكم في الإصدار لمعرفة ما يجب عليهم فعله لجعله يعمل - والفشل! - الطريق الصحيح.

الأشياء الأخرى التي تبحث عنها في وضع قيود كافية على بيئة Python التي لا يوجد شيء مثل الحل العام.

إليك شيء يقوم بتنفيذ #1 إلى حد ما

>>> import pickle
>>> def identify(f):
...   name = f.__name__
...   module_name = pickle.whichmodule(f, name)
...   return module_name + "." + name
... 
>>> identify(math.cos)
'math.cos'
>>> from xml.sax.saxutils import handler
>>> identify(handler)
'__main__.xml.sax.handler'
>>> 

رقم 3 الخاص بك غير محدد. إذا فعلت

__builtin__.step = path.to.your.stap

ثم هل يجب أن يجد رمز البحث "خطوة"؟

أبسط تطبيق يمكنني التفكير فيه ببساطة في البحث عن جميع الوحدات النمطية والبحث عن العناصر ذات المستوى الأعلى والتي هي بالضبط ما تريده

>>> import sys
>>> def _find_paths(x):
...   for module_name, module in sys.modules.items():
...     if module is None:
...         continue
...     for (member_name, obj) in module.__dict__.items():
...       if obj is x:
...         yield module_name + "." + member_name
... 
>>> def find_shortest_name_to_object(x):
...   return min( (len(name), name) for name in _find_paths(x) )[1]
... 
>>> find_shortest_name_to_object(handler)
'__builtin__._'
>>> 5
5
>>> find_shortest_name_to_object(handler)
'xml.sax.handler'
>>> 

هنا يمكنك أن ترى أن "المعالج" كان بالفعل في _ من عودة التعبير السابقة ، مما يجعله أقصر اسم.

إذا كنت تريد شيئًا آخر ، مثل البحث بشكل متكرر في جميع أعضاء جميع الوحدات ، فما عليك سوى ترميزه. ولكن كما يظهر مثال "_" ، ستكون هناك مفاجآت. بالإضافة إلى ذلك ، هذا غير مستقر ، لأن استيراد وحدة أخرى قد يجعل مسار كائن آخر متاحًا وأقصر.

لهذا السبب يقول الناس مرارًا وتكرارًا أن ما تريده ليس مفيدًا بالفعل لأي شيء ، ولهذا السبب لا توجد وحدات لذلك.

أما بالنسبة لرقم رقم 4 الخاص بك ، كيف في العالم سوف تلبي أي حزمة عامة لاحتياجات التسمية؟

في أي حال ، كتبت

من فضلك ، لا تحاول أن تريني تنفيذًا سريعًا لهذه الأشياء. إنه أكثر تعقيدًا مما يبدو ، هناك الكثير من gotchas ، وربما يفشل أي رمز سريع n-dirty في العديد من الحالات المهمة. هذا النوع من المهام تدعو إلى الكود الذي تم اختباره في المعركة.

لذلك لا تفكر في أمثلةي كحلول ، ولكن كأمثلة على سبب عدم طلب ما تطلبه. إنها مساحة حل هشة ADN القليلة الذين يغامرون هناك (معظمهم من أجل الفضول) لديهم مخاوف مختلفة لدرجة أن الحل المخصص لمرة واحدة هو أفضل شيء. إن الوحدة النمطية لمعظم هذه الأشياء لا معنى لها ، وإذا كان من المنطقي أن يكون تفسير ما تفعله الوحدة أطول من الكود.

وبالتالي الإجابة على سؤالك هي "لا ، لا توجد مثل هذه الوحدات".

ما الذي يجعل سؤالك أكثر إرباكًا هو أن تنفيذ C للبيثون يحدد بالفعل "عنوان كائن". ال مستندات لـ ID () قل:

تفاصيل تنفيذ Cpython: هذا هو عنوان الكائن.

ما تبحث عنه هو الاسم ، أو المسار إلى الكائن. ليس "عنوان كائن بيثون".

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top