سؤال

لنفترض أنني بحاجة إلى إنشاء DSL الصغيرة الخاصة بي التي من شأنها أن تستخدم Python لوصف بنية بيانات معينة. على سبيل المثال ، أود أن أتمكن من كتابة شيء مثل

f(x) = some_stuff(a,b,c)

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

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

e = Expression()
e.f[e.x] = e.some_stuff(e.a, e.b, e.c)

سيكون من الرائع رغم ذلك ، إذا كان من الممكن التخلص من "هـ" المزعج. البادئات وربما حتى تجنب استخدام []. لذلك كنت أتساءل ، هل من الممكن أن يكون "إعادة تعريف" عمليات البحث والمهام العالمية بشكل مؤقت؟ في ملاحظة ذات صلة ، ربما هناك حزم جيدة لتحقيق هذه الوظائف "الاقتباس" بسهولة لتعبيرات بيثون؟

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

المحلول

لست متأكدًا من أنها فكرة جيدة ، لكنني اعتقدت أنني سأفعل ذلك جربها. كي تختصر:

class PermissiveDict(dict):
    default = None

    def __getitem__(self, item):
        try:
            return dict.__getitem__(self, item)
        except KeyError:
            return self.default

def exec_with_default(code, default=None):
    ns = PermissiveDict()
    ns.default = default
    exec code in ns
    return ns

نصائح أخرى

قد ترغب في إلقاء نظرة على ast أو parser الوحدات النمطية المدرجة مع Python لتحليل ، وصول وتحويل شجرة بناء الجملة المجردة (أو شجرة التحليل ، على التوالي) من رمز الإدخال. بقدر ما أعرف ، النظام الرياضي حكيم, ، مكتوب في بيثون ، لديه نوع مماثل من premompiler.

استجابةً لتعليق Wai ، إليك حلًا ممتعًا وجدته. بادئ ذي بدء ، لشرح ما يفعله مرة أخرى ، لنفترض أن لديك الكود التالي:

definitions = Structure()
definitions.add_definition('f[x]', 'x*2')
definitions.add_definition('f[z]', 'some_function(z)')
definitions.add_definition('g.i', 'some_object[i].method(param=value)')

حيث تضيف إضافة تعريفات توصيل الجوانب اليسرى والجانبين اليمنى والقيام بأشياء قبيحة أخرى. الآن ، سيسمح نهج واحد (ليس جيدًا بالضرورة ، ولكن بالتأكيد ممتع) لكتابة الرمز أعلاه على النحو التالي:

@my_dsl
def definitions():
    f[x] = x*2
    f[z] = some_function(z)
    g.i  = some_object[i].method(param=value)

واطلب من بيثون القيام بمعظم التحليل تحت الغطاء. تعتمد الفكرة على البسيط exec <code> in <environment> بيان ، ذكره إيان ، مع إضافة واحدة. وهي ، يجب أن يتم تعديل رمز الوظيفة قليلاً وتبديل جميع عمليات الوصول المتغيرة المحلية (LOAD_FAST) إلى الوصول المتغير من البيئة (LOAD_NAME).

يتم عرضه أسهل مما هو موضح: http://fouryears.eu/wp-content/uploads/pydsl/

هناك العديد من الحيل التي قد ترغب في القيام بها لجعلها عملية. على سبيل المثال ، في الكود المقدم في الرابط أعلاه ، لا يمكنك استخدام وظائف مدمجة وأنشأات اللغة مثل الحلقات وإذا كانت عبارات داخل وظيفة my_dsl. ومع ذلك ، يمكنك جعل هذه العمل ، عن طريق إضافة المزيد من السلوك إلى فئة ENV.

تحديث. هنا هو تفسير مطوّل أكثر قليلاً لنفس الشيء.

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