كيف تعرف عند النظر إلى قائمة السمات والأساليب المدرجة في dir وهي سمات وأي طرق؟

StackOverflow https://stackoverflow.com/questions/880160

سؤال

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

هنا هو الكود الأصلي:

class Die(object):
''' simulate a six-sided die '''
def roll(self):
    self.value=random.randrange(1,7)
    return self.value
def getValue(self):
    return self.value

كنت أنظر إلى ذلك ، وبعد إنشاء بعض الحالات ، تساءلت عما إذا كانت قيمة الكلمة عبارة عن كلمة رئيسية بطريقة أو بأخرى وما هو استخدام الكائن في عبارة الفصل ، ولذا قررت معرفة ذلك من خلال تغيير تعريف الفئة إلى ما يلي:

class Die():
''' simulate a six-sided die '''
def roll(self):
    self.ban=random.randrange(1,7)
    return self.ban
def getValue(self):
    return self.ban

أظهر لي هذا التغيير أنني حصلت على نفس السلوك من مثيلاتي ، لكن الأساليب/السمات التالية كانت مفقودة من الحالات عندما فعلت:

'__class__', '__delattr__', '__dict__', '__doc__', '__getattribute__',
 '__hash__', '__init__', '__module__', '__new__', '__reduce__', '__reduce_ex__',
_repr__', '__setattr__', '__str__', '__weakref__'

لقد اكتشفت أيضًا أنه عندما فعلت dir على مثيل ، كان لدي كلمة رئيسية إضافية-المنع الذي اكتشفته أخيرًا كانت سمة مثيلتي. ساعدني هذا في فهم أنه يمكنني استخدامه d1.ban للوصول إلى قيمة المثيل الخاص بي. السبب الوحيد الذي جعلني أتمكن من معرفة أن هذه سمة كانت كتبت d1.happy وحصلت على نمة لقد اكتشفت ذلك D1.GetValue كانت طريقة مرتبطة بالموت لأن هذا ما أخبرني به المترجم.

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

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

['__doc__', '__module__', 'ban', 'getValue', 'roll']

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

بعد نشر السؤال حاولت

for each in dir(d1):
    print hasattr(d1,each)

الذي يخبرني بالمعنى الدلالي أن جميع الأساليب هي سمات. لكن لا يمكنني استدعاء طريقة بدون () لذلك يبدو لي أن hasattr () مضللة.

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

المحلول

بدلاً من: "print hasattr(d1,each)"، محاولة: "print each, type(getattr(d1,each))". يجب أن تجد النتائج مفيدة.

أيضا ، بدلا من dir() محاولة help(), ، والتي أعتقد أنك تبحث عنها حقًا.

نصائح أخرى

فكر في استخدام المكتبة القياسية inspect الوحدة النمطية-غالبًا ما يكون النهج الأكثر سهولة للتأمل ، وتعبئة أجزاء كبيرة من الوظائف (يمكنك تنفيذ ذلك من نقطة الصفر ، ولكن إعادة استخدام الكود الذي تم اختباره جيدًا ومصمم جيدًا أمر جيد). نرى http://docs.python.org/library/insprice.html لجميع التفاصيل ، ولكن على سبيل المثال inspect.getmembers(foo, inspect.ismethod) هي وسيلة ممتازة للحصول على جميع طرق فو (ستحصل (name, value) أزواج مرتبة بالاسم).

الذي يخبرني بالمعنى الدلالي أن جميع الأساليب هي سمات. لكن لا يمكنني استدعاء طريقة بدون () لذلك يبدو لي أن Hasattr () مضللة.

لماذا هي مضللة؟ إذا obj.ban() هي طريقة ، إذن obj.ban هي السمة المقابلة. يمكنك الحصول على رمز مثل هذا:

print obj.getValue()

أو

get = obj.getValue
print get()

إذا كنت ترغب في الحصول على قائمة بالطرق على كائن ، يمكنك تجربة هذه الوظيفة. إنه ليس مثاليًا ، لأنه سيؤدي أيضًا إلى تشغيل سمات قابلة للاستدعاء ليست طرقًا ، ولكن يجب أن تكون 99 ٪ من الحالات جيدة بما يكفي:

def methods(obj):
    attrs = (getattr(obj, n) for n in dir(obj))
    return [a for a in attrs if a.hasattr("__call__")]

هذه info الوحدة المستوحاة من الغوص في بيثون تخدم الغرض.

def info(obj, spacing=20, collapse=1, variables=False):
    '''Print methods and their doc Strings

    Takes any object'''
    if variables:
    methodList = [method for method in dir(obj)]
    else:
    methodList = [method for method in dir(obj) if callable(getattr(obj,method))]

    #print methodList


    print '\n'.join(['%s %s' %
            (method.ljust(spacing),
             " ".join(str(getattr(obj,method).__doc__).split()))
            for method in methodList])


if __name__=='__main__':
    info(list)

هناك طريقة مدمجة تسمى callable. يمكنك تطبيقه على أي كائن وسيعود True/False اعتمادًا على ما إذا كان يمكن استدعاؤه. على سبيل المثال

>>> def foo():
...   print "This is the only function now"
...
>>> localDictionary = dir()
>>> for item in localDictionary:
...   print repr(item) + "is callable: " + str(callable(locals()[item]))
'__builtins__'is callable: False
'__doc__'is callable: False
'__name__'is callable: False
'foo'is callable: True

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

من الناحية المثالية ، عند استخدام مكتبة معقدة مثل BeautifulSoup ، يجب عليك استشارة وثائقها لمعرفة الأساليب التي يوفرها كل فصل. ومع ذلك ، في الحالة النادرة حيث لا يكون لديك وثائق يمكن الوصول إليها بسهولة ، يمكنك التحقق من وجود طرق باستخدام ما يلي.

جميع الطرق ، التي هي نفسها كائنات ، تنفذ __call__ الطريقة ويمكن فحصها باستخدام طريقة callable () التي تعود True, ، إذا كانت القيمة التي يتم فحصها لديها __call__ طريقة.

يجب أن يعمل الرمز التالي.

x = Die()
x.roll()

for attribute in dir(x) :
    print attribute, callable(getattr(x, attribute))

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

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