আপনি কি পাইথনের সিনট্যাক্সে নতুন বিবৃতি যুক্ত করতে পারেন?


124

আপনি নতুন বিবৃতি (যেমন যোগ করতে পারেন print, raise, withপাইথন এর সিনট্যাক্স)?

বলুন, অনুমতি দিন ..

mystatement "Something"

অথবা,

new_if True:
    print "example"

আপনার করা উচিত এতটা না , তবে এটি সম্ভব হলে (পাইথন ইন্টারপ্রেটার কোড সংশোধন করার সংক্ষিপ্ত)


10
কিছুটা সম্পর্কিত নোটে, একটি ব্যবহারের ক্ষেত্রে যেখানে ফ্লাইয়ে নতুন বক্তব্য তৈরি করা সহজ হতে পারে (ভাষাটিকে গুরুত্বের সাথে "প্রসারিত করার" বিপরীতে) সেই লোকদের জন্য যারা ইন্টারেক্টিভ ইন্টারপ্রেটারকে ক্যালকুলেটর হিসাবে ব্যবহার করেন, এমনকি একটি ওএস শেলও is । আমি প্রায়শই আবার যাচ্ছি এমন কিছু করার জন্য আমি ফ্লাইয়ের উপরে সামান্য ছুড়ে ফাংশন তৈরি করি এবং সেই পরিস্থিতিতে ফাংশন () সিনট্যাক্সের সাহায্যে দীর্ঘ নাম লেখার চেয়ে ম্যাক্রো বা স্টেটমেন্টের মতো খুব সংক্ষেপিত কমান্ড তৈরি করা ভাল হবে। অবশ্যই এটি পাই এর জন্য আসলেই নয় .. তবে লোকেরা এটি ইন্টারেক্টিভভাবে ব্যবহার করে অনেক সময় ব্যয় করে।
কিলো

5
@ কিলো এটি আইপথনটি দেখার মতো হতে পারে - এতে প্রচুর শেল বৈশিষ্ট্য রয়েছে, উদাহরণস্বরূপ আপনি নিয়মিত "এলএস" এবং "সিডি" কমান্ড, ট্যাব সমাপ্তি, প্রচুর ম্যাক্রো-ইশ বৈশিষ্ট্য ইত্যাদি ব্যবহার করতে পারেন
ডিবিআর

কিছু ভাষাগুলি অতিমাত্রায় এক্সটেনসিবল, উদাহরণস্বরূপ ফোর্থ এবং স্মলটালক, তবে তাদের ভাষার উদাহরণগুলি পাইথনের ব্যবহারের চেয়ে পৃথক। এই উভয় নতুন শব্দ (ফোরথ) বা পদ্ধতিগুলি (স্মার্টটাক) সেই সংস্থার জন্য ভাষার একটি অবিচ্ছেদ্য, অনিবার্য অঙ্গ হয়ে যায়। সুতরাং প্রতিটি ফোর্থ বা স্মলটাক ইনস্টলেশন সময়ের সাথে সাথে একটি অনন্য সৃষ্টি হয়ে যায়। এছাড়াও ফোর্থটি আরপিএন ভিত্তিক। তবে ডিএসএলগুলির লাইন ধরে চিন্তা করে, পাইথনে এর মতো কিছু করা উচিত। যদিও অন্যরা এখানে বলেছে, কেন?

1
পাইথন এবং ফোর্থ উভয় ক্ষেত্রেই কেউ সাবলীল হিসাবে, এবং যিনি বহু বছর ধরে বেশ কয়েকটি ফোর্থ সংকলক প্রয়োগ করেছেন, আমি কিছুটা কর্তৃত্বের সাথে এখানে অবদান রাখতে পারি। পাইথনের অভ্যন্তরীণ পার্সারে কাঁচা অ্যাক্সেস না পেয়ে এটি সম্পূর্ণ অসম্ভব। নীচে (স্পষ্টতই, বরং চটজলদি!) উত্তরগুলি চিত্রিত করে আপনি প্রিপ্রোসেসিং করে এটি জাল করতে পারেন, তবে সত্যিকার অর্থে একটি گرم দোভাষীটিতে ভাষার বাক্য গঠন এবং / বা শব্দার্থবিজ্ঞানকে আপডেট করা সম্ভব নয়। এটি পাইথনের অভিশাপ এবং পাশাপাশি লিস্প- এবং ফোরথ-এর মতো ভাষার উপর এটির সুবিধা।
স্যামুয়েল এ। ফালভো II

উত্তর:


153

আপনি এটি দরকারী খুঁজে পেতে পারেন - পাইথন ইন্টার্নালস: এখানে উদ্ধৃত পাইথনে একটি নতুন বিবৃতি যুক্ত :


এই নিবন্ধটি পাইথনের সম্মুখ-প্রান্তটি কীভাবে কাজ করে তা আরও ভাল করে বোঝার একটি প্রচেষ্টা। কেবলমাত্র ডকুমেন্টেশন এবং উত্স কোড পড়া কিছুটা বিরক্তিকর হতে পারে, তাই আমি এখানে হাতছাড়া পন্থা নিচ্ছি: আমি untilপাইথনে একটি বিবৃতি যুক্ত করতে যাচ্ছি ।

এই নিবন্ধটির সমস্ত কোডিং পাইথন মার্কিউরিয়াল রিপোজিটরি আয়নাতে কাটিং-এজ পাই 3 কে শাখার বিপরীতে করা হয়েছিল ।

untilবিবৃতি

কিছু ভাষায়, রুবির মতো একটি untilবক্তব্য রয়েছে, যা পরিপূরক while( until num == 0সমতুল্য while num != 0)। রুবিতে আমি লিখতে পারি:

num = 3
until num == 0 do
  puts num
  num -= 1
end

এবং এটি মুদ্রণ করবে:

3
2
1

সুতরাং, আমি পাইথনের সাথে অনুরূপ সামর্থ্য যুক্ত করতে চাই। এটি, লিখতে সক্ষম হচ্ছে:

num = 3
until num == 0:
  print(num)
  num -= 1

একটি ভাষা-অ্যাডভোকেসি ডিগ্রেশন

এই নিবন্ধটি untilপাইথনে একটি বিবৃতি যুক্ত করার চেষ্টা করার চেষ্টা করে না । যদিও আমি মনে করি যে এই জাতীয় বিবৃতিটি কিছু কোড পরিষ্কার করবে এবং এই নিবন্ধটি যুক্ত করা কত সহজ তা দেখায়, আমি পাইথনের সংক্ষিপ্ততার দর্শনের সম্পূর্ণ সম্মান করি। আমি এখানে যা করতে চাইছি তা হ'ল পাইথনের অভ্যন্তরীণ কার্যকারিতা সম্পর্কে কিছুটা অন্তর্দৃষ্টি অর্জন করা।

ব্যাকরণ পরিবর্তন করা

পাইথন একটি কাস্টম পার্সার জেনারেটর ব্যবহার করে pgen। এটি একটি এলএল (1) পার্সার যা পাইথন উত্স কোডটিকে পার্স ট্রিে রূপান্তর করে। পার্সার জেনারেটরের ইনপুটটি ফাইল Grammar/Grammar[1] । এটি একটি সাধারণ পাঠ্য ফাইল যা পাইথনের ব্যাকরণ নির্দিষ্ট করে।

[1] : এখান থেকে পাইথন উত্সের ফাইলগুলির উল্লেখগুলি উত্স গাছের মূলের তুলনায় তুলনামূলকভাবে দেওয়া হয়, এটি সেই ডিরেক্টরি যেখানে আপনি কনফিগার চালিয়ে পাইথন তৈরির জন্য তৈরি করেন make

ব্যাকরণ ফাইলে দুটি পরিবর্তন করতে হবে। প্রথমটি হল untilবিবৃতিটির জন্য একটি সংজ্ঞা যুক্ত করা । আমি খুঁজে পেয়েছি যেখানে whileবিবৃতিটি সংজ্ঞায়িত করা হয়েছিল ( while_stmt), এবং until_stmtনীচে যুক্ত করা হয়েছে [2] :

compound_stmt: if_stmt | while_stmt | until_stmt | for_stmt | try_stmt | with_stmt | funcdef | classdef | decorated
if_stmt: 'if' test ':' suite ('elif' test ':' suite)* ['else' ':' suite]
while_stmt: 'while' test ':' suite ['else' ':' suite]
until_stmt: 'until' test ':' suite

[২] : উত্স কোডটি সংশোধন করার সময় আমি যে সাধারণ ব্যবহার করি তা আমি প্রদর্শন করি: যার সাথে আমি পরিচিত নই: সাদৃশ্য অনুসারে কাজ করুন । এই নীতিটি আপনার সমস্ত সমস্যার সমাধান করবে না, তবে এটি অবশ্যই প্রক্রিয়াটি সহজ করতে পারে। যেহেতু যা করতে হবে তার whileজন্যও সমস্ত কিছু করা উচিত until, এটি একটি দুর্দান্ত ভাল গাইডলাইন হিসাবে কাজ করে।

নোট করুন যে আমি এই elseসংজ্ঞাটি untilকিছুটা আলাদা করার জন্য আমার সংজ্ঞাটি থেকে বাদ দেওয়ার সিদ্ধান্ত নিয়েছি (এবং প্রকৃতপক্ষে আমি elseলুপগুলির ধারাটিকে অপছন্দ করি এবং মনে করি না যে এটি পাইথনের জেনের সাথে ভাল ফিট করে)।

দ্বিতীয় পরিবর্তনটি compound_stmtঅন্তর্ভুক্ত করার নিয়মটি সংশোধন করা until_stmt, আপনি উপরের স্নিপেটে দেখতে পারেন। এটা ঠিক পরে while_stmt, আবার।

আপনি চালাতে যখন makeপরিবর্তন পরে Grammar/Grammar, বিজ্ঞপ্তি যে pgenপ্রোগ্রাম চালানো হয় পুনরায় জেনারেট Include/graminit.hএবং Python/graminit.c, এবং তারপর বিভিন্ন ফাইল পুনরায় কম্পাইল পেতে।

এএসটি প্রজন্মের কোডটি সংশোধন করা হচ্ছে

পাইথন পার্সার একটি পার্স গাছ তৈরি করার পরে, এই গাছটি একটি এএসটিতে রূপান্তরিত হয়, যেহেতু সংকলন প্রক্রিয়ার পরবর্তী পর্যায়ে এটিএসটি কাজ করার জন্য অনেক সহজ

সুতরাং, আমরা পরিদর্শন করতে Parser/Python.asdlযা পাইথনের এএসটিগুলির গঠনকে সংজ্ঞায়িত করে এবং আমাদের নতুন untilবিবৃতিটির জন্য আবার এএসটি নোড যুক্ত করবে , ঠিক নীচে while:

| While(expr test, stmt* body, stmt* orelse)
| Until(expr test, stmt* body)

আপনি যদি এখন চালনা করেন তবে makeলক্ষ্য করুন যে গুচ্ছ ফাইলগুলি সংকলনের আগে Parser/asdl_c.pyএএসটি সংজ্ঞা ফাইল থেকে সি কোড উত্পন্ন করতে চালিত হয়। Grammar/Grammarপ্রোগ্রামিংকে সহজ করার জন্য মিনি-ল্যাঙ্গুয়েজ (অন্য কথায়, একটি ডিএসএল) ব্যবহার করে পাইথন সোর্স কোডের এটি (যেমন ) অন্য উদাহরণ। এছাড়াও লক্ষ করুন যেহেতু Parser/asdl_c.pyপাইথন স্ক্রিপ্ট তাই এটি এক ধরণের বুটস্ট্র্যাপিং - স্ক্র্যাচ থেকে পাইথন তৈরি করতে পাইথন ইতিমধ্যে উপলব্ধ থাকতে হবে।

Parser/asdl_c.pyআমাদের নতুন সংজ্ঞায়িত এএসটি নোড (ফাইলগুলিতে Include/Python-ast.hএবং Python/Python-ast.c) পরিচালনা করার জন্য কোডটি উত্পন্ন করার সময় , আমাদের এখনও কোডটি লিখতে হবে যা কোনও প্রাসঙ্গিক গাছ নোডকে হাতে রূপান্তরিত করে। এটি ফাইলটিতে করা হয় Python/ast.c। সেখানে, নামের একটি ফাংশন ast_for_stmtপার্স গাছের নোডগুলিকে এএসটি নোডগুলিতে বিবৃতি দেওয়ার জন্য রূপান্তর করে। আবার, আমাদের পুরানো বন্ধু দ্বারা পরিচালিত while, আমরা switchযৌগিক বিবৃতিগুলি পরিচালনা করার জন্য ডানদিকে ঝাঁপিয়ে পড়ি এবং এর জন্য একটি ধারা যুক্ত করি until_stmt:

case while_stmt:
    return ast_for_while_stmt(c, ch);
case until_stmt:
    return ast_for_until_stmt(c, ch);

এখন আমাদের বাস্তবায়ন করা উচিত ast_for_until_stmt। এটা এখানে:

static stmt_ty
ast_for_until_stmt(struct compiling *c, const node *n)
{
    /* until_stmt: 'until' test ':' suite */
    REQ(n, until_stmt);

    if (NCH(n) == 4) {
        expr_ty expression;
        asdl_seq *suite_seq;

        expression = ast_for_expr(c, CHILD(n, 1));
        if (!expression)
            return NULL;
        suite_seq = ast_for_suite(c, CHILD(n, 3));
        if (!suite_seq)
            return NULL;
        return Until(expression, suite_seq, LINENO(n), n->n_col_offset, c->c_arena);
    }

    PyErr_Format(PyExc_SystemError,
                 "wrong number of tokens for 'until' statement: %d",
                 NCH(n));
    return NULL;
}

আবার, এই কোডটি সমানভাবে ঘনিষ্ঠভাবে দেখার সময়, এই ast_for_while_stmtপার্থক্যের সাথে যে untilআমি এই elseধারাটিকে সমর্থন না করার সিদ্ধান্ত নিয়েছি with যেমনটি প্রত্যাশা করা হয়েছিল, এএসটিটি পুনরাবৃত্তভাবে তৈরি করা ast_for_exprহয়েছে, শর্তটি প্রকাশের ast_for_suiteজন্য এবং untilবিবৃতিটির মূল অংশের মতো অন্যান্য এএসটি তৈরি করে ফাংশন ব্যবহার করে । অবশেষে, নামের একটি নতুন নোড Untilফিরে আসে।

নোট করুন যে আমরা nকিছু ম্যাক্রোর মতো NCHএবং ব্যবহার করে পার্স-ট্রি নোড অ্যাক্সেস করি CHILD। এগুলি বোঝার যোগ্য - তাদের কোডটি রয়েছে Include/node.h

ডাইগ্রেশন: এএসটি রচনা

আমি untilবিবৃতিটির জন্য একটি নতুন ধরণের এএসটি তৈরি করতে বেছে নিয়েছি , তবে আসলে এটি প্রয়োজনীয় নয়। বিদ্যমান কিছু এএসটি নোডের সংমিশ্রণটি ব্যবহার করে আমি কিছু কাজ সংরক্ষণ করতে এবং নতুন কার্যকারিতা বাস্তবায়ন করতে পারতাম:

until condition:
   # do stuff

কার্যত সমান:

while not condition:
  # do stuff

Untilনোড ইন তৈরি করার পরিবর্তে ast_for_until_stmt, আমি Notছোটবেলায় নোডের সাথে একটি Whileনোড তৈরি করতে পারতাম । যেহেতু এএসটি সংকলক ইতিমধ্যে এই নোডগুলি পরিচালনা করতে জানে তাই প্রক্রিয়াটির পরবর্তী ধাপগুলি এড়ানো যায়।

এএসটিগুলি বাইটোকোডে সংকলন করছে

পরবর্তী পদক্ষেপটি পাইথন বাইকোডে এএসটি সংকলন করছে। সংকলনের একটি মধ্যবর্তী ফলাফল রয়েছে যা একটি সিএফজি (কন্ট্রোল ফ্লো গ্রাফ), তবে যেহেতু একই কোডটি এটি পরিচালনা করে আমি আপাতত এই বিশদটি উপেক্ষা করব এবং এটি অন্য একটি লেখার জন্য রেখে দেব।

আমরা পরবর্তী কোডটি দেখতে যাচ্ছি Python/compile.c। এর নেতৃত্ব অনুসরণ করে while, আমরা ফাংশনটি খুঁজে পাই compiler_visit_stmt, যা বাইটোকোডে বিবৃতি সংকলনের জন্য দায়ী। আমরা এর জন্য একটি ধারা যুক্ত করি Until:

case While_kind:
    return compiler_while(c, s);
case Until_kind:
    return compiler_until(c, s);

আপনি যদি অবাক Until_kindহন তবে _stmt_kindএটি এএসটি সংজ্ঞা ফাইল থেকে স্বয়ংক্রিয়ভাবে উত্পন্ন একটি ধ্রুবক (আসলে গণনার মান ) Include/Python-ast.h। যাইহোক, আমরা কল করি compiler_untilযা অবশ্যই, এখনও বিদ্যমান নেই। আমি এক মুহুর্তে এটি পেয়ে যাব।

আপনি যদি আমার মতো কৌতূহলী হন তবে আপনি দেখতে পাবেন যে compiler_visit_stmtএটি অদ্ভুত। grepউত্স গাছের পরিমাণ নির্ধারণ করে না যেখানে এটি বলা হয়। যখন এটি হয়, কেবলমাত্র একটি বিকল্প থাকে - সি ম্যাক্রো-ফু। আসলে, একটি সংক্ষিপ্ত তদন্ত আমাদের VISITম্যাক্রোতে সংজ্ঞায়িত করে Python/compile.c:

#define VISIT(C, TYPE, V) {\
    if (!compiler_visit_ ## TYPE((C), (V))) \
        return 0; \

এটা তোলে ডাকা ব্যবহৃত হচ্ছে compiler_visit_stmtমধ্যে compiler_body। আমাদের ব্যবসায় ফিরে যান, তবে ...

প্রতিশ্রুতি হিসাবে, এখানে compiler_until:

static int
compiler_until(struct compiler *c, stmt_ty s)
{
    basicblock *loop, *end, *anchor = NULL;
    int constant = expr_constant(s->v.Until.test);

    if (constant == 1) {
        return 1;
    }
    loop = compiler_new_block(c);
    end = compiler_new_block(c);
    if (constant == -1) {
        anchor = compiler_new_block(c);
        if (anchor == NULL)
            return 0;
    }
    if (loop == NULL || end == NULL)
        return 0;

    ADDOP_JREL(c, SETUP_LOOP, end);
    compiler_use_next_block(c, loop);
    if (!compiler_push_fblock(c, LOOP, loop))
        return 0;
    if (constant == -1) {
        VISIT(c, expr, s->v.Until.test);
        ADDOP_JABS(c, POP_JUMP_IF_TRUE, anchor);
    }
    VISIT_SEQ(c, stmt, s->v.Until.body);
    ADDOP_JABS(c, JUMP_ABSOLUTE, loop);

    if (constant == -1) {
        compiler_use_next_block(c, anchor);
        ADDOP(c, POP_BLOCK);
    }
    compiler_pop_fblock(c, LOOP, loop);
    compiler_use_next_block(c, end);

    return 1;
}

আমার কাছে একটি স্বীকারোক্তি আছে: পাইথন বাইকোডের গভীর বোঝার ভিত্তিতে এই কোডটি লেখা হয়নি। নিবন্ধের বাকী অংশগুলির মতো এটিও আত্মীয় compiler_whileকার্যের অনুকরণে করা হয়েছিল । এটিকে সাবধানে পড়ার মাধ্যমে, পাইথন ভিএম স্ট্যাক-ভিত্তিক এবং disমডিউলের ডকুমেন্টেশনের দিকে ঝুঁকছেন, যেখানে বিবরণ সহ পাইথন বাইটকোডগুলির একটি তালিকা রয়েছে , এটি বোঝা যায় যে কী চলছে।

এটাই, আমরা শেষ করেছি ... আমরা না?

সমস্ত পরিবর্তন এবং চলমান পরে make, আমরা নতুন সংকলিত পাইথন চালাতে এবং আমাদের নতুন untilবিবৃতি চেষ্টা করতে পারেন :

>>> until num == 0:
...   print(num)
...   num -= 1
...
3
2
1

ভয়েলা, কাজ করে! নীচে disমডিউলটি ব্যবহার করে নতুন বিবৃতিটির জন্য তৈরি বাইটকোডটি দেখুন :

import dis

def myfoo(num):
    until num == 0:
        print(num)
        num -= 1

dis.dis(myfoo)

ফলাফল এখানে:

4           0 SETUP_LOOP              36 (to 39)
      >>    3 LOAD_FAST                0 (num)
            6 LOAD_CONST               1 (0)
            9 COMPARE_OP               2 (==)
           12 POP_JUMP_IF_TRUE        38

5          15 LOAD_NAME                0 (print)
           18 LOAD_FAST                0 (num)
           21 CALL_FUNCTION            1
           24 POP_TOP

6          25 LOAD_FAST                0 (num)
           28 LOAD_CONST               2 (1)
           31 INPLACE_SUBTRACT
           32 STORE_FAST               0 (num)
           35 JUMP_ABSOLUTE            3
      >>   38 POP_BLOCK
      >>   39 LOAD_CONST               0 (None)
           42 RETURN_VALUE

সর্বাধিক আকর্ষণীয় অপারেশনটি 12 নম্বর: শর্তটি সত্য হলে আমরা লুপের পরে ঝাঁপ দাও। এটি সঠিক শব্দার্থবিজ্ঞানের জন্য until। যদি লাফটি কার্যকর না করা হয়, অপারেশন ৩৫-এর শর্তে ফিরে না আসা পর্যন্ত লুপ বডিটি চলতে থাকে।

আমার পরিবর্তন সম্পর্কে ভাল লাগছে, আমি তখন ফাংশনটি চালানোর চেষ্টা করেছি (সম্পাদন myfoo(3)) এর বাইকোড না দেখানোর পরিবর্তে। ফলাফল উত্সাহ দেওয়ার চেয়ে কম ছিল:

Traceback (most recent call last):
  File "zy.py", line 9, in
    myfoo(3)
  File "zy.py", line 5, in myfoo
    print(num)
SystemError: no locals when loading 'print'

ওহো ... এটা ভাল হতে পারে না। তাহলে কি ভুল হয়েছে?

নিখোঁজ প্রতীক টেবিল কেস

এএসটি সংকলন করার সময় পাইথন সংকলক যে পদক্ষেপগুলি সম্পাদন করে তার মধ্যে একটি হল কোডটি সংকলন করে তার জন্য একটি সারণী সারণী তৈরি করা। থেকে কল PySymtable_Buildমধ্যে PyAST_Compileপ্রতীক টেবিল মডিউল (মধ্যে কল Python/symtable.c), যা একটি পদ্ধতিতে কোড নির্মাণ ফাংশন অনুরূপ এবং AST দিয়ে হেঁটে যাচ্ছে। প্রতিটি স্কোপের জন্য একটি সারণী সারণী থাকা সংকলকটিকে কিছু মূল তথ্য বের করতে সহায়তা করে, যেমন কোন ভেরিয়েবলগুলি বিশ্বব্যাপী এবং কোন স্কোপে স্থানীয়।

সমস্যার সমাধানের জন্য, বিবৃতিগুলির জন্য একই কোডের পরে, আমাদের বিবৃতি পরিচালনা করতে কোড যুক্ত করে symtable_visit_stmtফাংশনটি সংশোধন করতে হবে [3] :Python/symtable.cuntilwhile

case While_kind:
    VISIT(st, expr, s->v.While.test);
    VISIT_SEQ(st, stmt, s->v.While.body);
    if (s->v.While.orelse)
        VISIT_SEQ(st, stmt, s->v.While.orelse);
    break;
case Until_kind:
    VISIT(st, expr, s->v.Until.test);
    VISIT_SEQ(st, stmt, s->v.Until.body);
    break;

[3] : যাইহোক, এই কোড ব্যতীত এর জন্য একটি সংকলক সতর্কতা রয়েছে Python/symtable.c। সংকলকটি লক্ষ্য করে যে Until_kindগণনার মানটি স্যুইচ বিবৃতিতে symtable_visit_stmtঅভিযোগ করা হয় না এবং অভিযোগ করে না। সংকলক সতর্কতাগুলির জন্য এটি পরীক্ষা করা সবসময় গুরুত্বপূর্ণ!

এবং এখন আমরা সত্যিই সম্পন্ন। এই পরিবর্তনের পরে উত্সটি সংকলন myfoo(3)করা প্রত্যাশার মতো করে কাজ সম্পাদন করে ।

উপসংহার

এই নিবন্ধে আমি দেখিয়েছি কীভাবে পাইথনে একটি নতুন বিবৃতি যুক্ত করতে হয়। পাইথন সংকলকের কোডে যদিও বেশ কিছুটা ঝোঁক প্রয়োজন, পরিবর্তনটি বাস্তবায়ন করা খুব কঠিন ছিল না, কারণ আমি গাইডলাইন হিসাবে অনুরূপ এবং বিদ্যমান বক্তব্যটি ব্যবহার করেছি।

পাইথন সংকলকটি সফ্টওয়্যারটির একটি পরিশীলিত অংশ এবং আমি এটিতে বিশেষজ্ঞ হিসাবে দাবি করি না। তবে আমি পাইথনের অভ্যন্তরীণ ক্ষেত্রগুলিতে এবং বিশেষত এর ফ্রন্ট-এন্ডে আগ্রহী। অতএব, আমি এই অনুশীলনটি সংকলকের নীতি এবং উত্স কোডের তাত্ত্বিক অধ্যয়নের জন্য খুব দরকারী সহযোগী হিসাবে পেয়েছি। এটি ভবিষ্যতের নিবন্ধগুলির ভিত্তি হিসাবে কাজ করবে যা সংকলকটির আরও গভীর হবে।

তথ্যসূত্র

আমি এই নিবন্ধটি নির্মাণের জন্য কয়েকটি দুর্দান্ত রেফারেন্স ব্যবহার করেছি। এখানে তারা কোনও নির্দিষ্ট ক্রমে নয়:

  • পিইপি 339: সিপথন সংকলকটির ডিজাইন - পাইথন সংকলকটির পক্ষে সম্ভবত অফিসিয়াল ডকুমেন্টেশনের সবচেয়ে গুরুত্বপূর্ণ এবং বিস্তৃত অংশ । খুব সংক্ষিপ্ত হওয়ার কারণে এটি পাইথনের ইন্টার্নালগুলির ভাল ডকুমেন্টেশনের অভাবটি বেদনাদায়কভাবে প্রদর্শন করে।
  • "পাইথন সংকলক অভ্যন্তরীণ" - টমাস লি-র একটি নিবন্ধ
  • "পাইথন: ডিজাইন এবং বাস্তবায়ন" - গাইডো ভ্যান রসমের উপস্থাপনা
  • পাইথন (2.5) ভার্চুয়াল মেশিন, একটি গাইড ট্যুর - পিটার ট্র্যাজারের উপস্থাপনা

মূল উৎস


7
দুর্দান্ত নিবন্ধ (/ ব্লগ), ধন্যবাদ! যেহেতু এটি পুরোপুরি প্রশ্নের জবাব দেয় তাই গ্রহণ করা এবং "এটি করবেন না" / "কোডিং: মাইলাং" উত্তরগুলি ইতিমধ্যে অত্যন্ত আপত্তিজনক, তাই
সাজানোতে

1
তবে দুর্ভাগ্যক্রমে, এটি কোনও উত্তর নয়। লিঙ্কযুক্ত নিবন্ধটি হল, তবে আপনি উত্সাহ দিতে বা গ্রহণ করতে পারবেন না। কেবলমাত্র একটি লিঙ্কের সম্পূর্ণ উত্তরগুলি নিরুৎসাহিত করা হয়।
Alfe

6
@ আলফা: এটি দুই বছর আগে পোস্ট করা হয়েছিল, 16 টি পাঠক গ্রহণ করেছেন এবং এটি +1 করেছেন। মনে রাখবেন এটি আমার নিজের ব্লগ পোস্টের সাথে লিঙ্ক করে এবং স্ট্যাকওভারফ্লোতে একটি বৃহত্তর নিবন্ধ অনুলিপি করা আমার ইচ্ছা মতো কিছু নয়। পুলিশ বাজানোর পরিবর্তে কোনও দরকারী সম্পাদনায় এটি নির্দ্বিধায় করুন।
এলি বেন্ডারস্কি

2
@ এলিবেেন্ডারস্কি দরকারী এই নিবন্ধটির জন্য যথেষ্ট সংক্ষিপ্ত বিবরণ। পাইথনগুলিতে এই জিনিসগুলি আসলে কীভাবে কাজ করে সে সম্পর্কে এতগুলি ব্যাখ্যা করার জন্য ধন্যবাদ। এটি আমাকে সত্যই এটিএসটি বুঝতে সহায়তা করেছে যা আমার বর্তমান কাজের সাথে প্রাসঙ্গিক। ** এছাড়াও, আপনি যদি কৌতূহলী হন তবে আমার সংস্করণটি untilহ'ল isa/ isanহিসাবে if something isa dict:বাif something isan int:
ইনভারসাস

5
হ্যাঁ, এই উত্তরটি "পাইথন থেকে কাঁটা উত্স থেকে আপনার নিজস্ব ভাষা লিখুন এবং সংকলন করুন"
থারস্মমনার

53

এর মতো কাজ করার একটি উপায় হ'ল উত্সকে প্রস্রোস করা এবং এটিকে সংশোধন করা, আপনার যুক্ত বিবৃতিটি অজগরকে অনুবাদ করা। বিভিন্ন ধরণের সমস্যা রয়েছে যা এই পদ্ধতিটি নিয়ে আসবে, এবং আমি এটিকে সাধারণ ব্যবহারের জন্য সুপারিশ করব না, তবে ভাষা, বা নির্দিষ্ট-উদ্দেশ্য রূপক পরীক্ষার জন্য এটি কখনও কখনও কার্যকর হতে পারে।

উদাহরণস্বরূপ, আসুন আমরা বলি যে আমরা একটি "মাইপ্রিন্ট" বিবৃতি প্রবর্তন করতে চাই, যে স্ক্রিনে মুদ্রণের পরিবর্তে একটি নির্দিষ্ট ফাইলে লগইন হয়। অর্থাৎ,

myprint "This gets logged to file"

সমান হবে

print >>open('/tmp/logfile.txt','a'), "This gets logged to file"

আপনার সিনট্যাক্স বিদ্যমান পাইথনের সাথে কীভাবে মিলিত হয় তার উপর নির্ভর করে আপনার নিজের পার্সার লিখতে রিজেক্স সাবস্টিটিউশন থেকে এটিএসটি তৈরির ক্ষেত্রে কীভাবে প্রতিস্থাপনটি করা যায় সে সম্পর্কে বিভিন্ন বিকল্প রয়েছে। টোকেনাইজার মডিউলটি ব্যবহার করা একটি ভাল মধ্যবর্তী পন্থা। পাইথন ইন্টারপ্রেটারের অনুরূপ উত্সকে ব্যাখ্যা করার সময় এটি আপনাকে নতুন কীওয়ার্ড, নিয়ন্ত্রণ কাঠামো ইত্যাদির যোগ করার অনুমতি দেয়, এইভাবে ভাঙ্গা ক্রুড রেজেক্স সমাধানগুলি এড়াতে পারে। উপরের "মাইপ্রিন্ট" এর জন্য আপনি নিম্নলিখিত রূপান্তর কোডটি লিখতে পারেন:

import tokenize

LOGFILE = '/tmp/log.txt'
def translate(readline):
    for type, name,_,_,_ in tokenize.generate_tokens(readline):
        if type ==tokenize.NAME and name =='myprint':
            yield tokenize.NAME, 'print'
            yield tokenize.OP, '>>'
            yield tokenize.NAME, "open"
            yield tokenize.OP, "("
            yield tokenize.STRING, repr(LOGFILE)
            yield tokenize.OP, ","
            yield tokenize.STRING, "'a'"
            yield tokenize.OP, ")"
            yield tokenize.OP, ","
        else:
            yield type,name

(এটি মাইপ্রিন্টকে কার্যকরভাবে একটি কীওয়ার্ড বানায়, তাই অন্যত্র ভেরিয়েবল হিসাবে ব্যবহার করা সমস্যার কারণ হতে পারে)

তারপরে সমস্যাটি হ'ল কীভাবে এটি ব্যবহার করবেন যাতে আপনার কোডটি অজগর থেকে ব্যবহারযোগ্য। একটি উপায় হ'ল আপনার নিজের আমদানি ফাংশনটি লিখুন এবং এটি আপনার কাস্টম ভাষায় লিখিত কোড লোড করতে ব্যবহার করুন। অর্থাৎ,

import new
def myimport(filename):
    mod = new.module(filename)
    f=open(filename)
    data = tokenize.untokenize(translate(f.readline))
    exec data in mod.__dict__
    return mod

এর জন্য আপনাকে সাধারণ অজগর মডিউলগুলির চেয়ে আলাদাভাবে নিজের কাস্টমাইজড কোডটি পরিচালনা করতে হবে। যেমন " some_mod = myimport("some_mod.py")" এর চেয়ে " import some_mod"

আর একটি মোটামুটি ঝরঝরে (হ্যাকি হওয়া সত্ত্বেও) সমাধান হ'ল এই রেসিপিটি যেমন দেখায় তেমন একটি কাস্টম এনকোডিং তৈরি করা ( পিইপি 263 দেখুন ) । আপনি এটি প্রয়োগ করতে পারেন:

import codecs, cStringIO, encodings
from encodings import utf_8

class StreamReader(utf_8.StreamReader):
    def __init__(self, *args, **kwargs):
        codecs.StreamReader.__init__(self, *args, **kwargs)
        data = tokenize.untokenize(translate(self.stream.readline))
        self.stream = cStringIO.StringIO(data)

def search_function(s):
    if s!='mylang': return None
    utf8=encodings.search_function('utf8') # Assume utf8 encoding
    return codecs.CodecInfo(
        name='mylang',
        encode = utf8.encode,
        decode = utf8.decode,
        incrementalencoder=utf8.incrementalencoder,
        incrementaldecoder=utf8.incrementaldecoder,
        streamreader=StreamReader,
        streamwriter=utf8.streamwriter)

codecs.register(search_function)

এখন এই কোডটি চালুর পরে (যেমন, আপনি এটি আপনার .Pythonrc বা site.py এ স্থাপন করতে পারেন) "# কোডিং: মাইলং" মন্তব্য দিয়ে শুরু হওয়া কোনও কোড স্বয়ংক্রিয়ভাবে উপরের প্রাকপ্রসেসিং পদক্ষেপের মাধ্যমে অনুবাদ করা হবে। যেমন।

# coding: mylang
myprint "this gets logged to file"
for i in range(10):
    myprint "so does this : ", i, "times"
myprint ("works fine" "with arbitrary" + " syntax" 
  "and line continuations")

আদেশ সহকারে:

প্রিপ্রসেসর পদ্ধতির সমস্যা রয়েছে, কারণ আপনি যদি সি প্রিপ্রসেসরের সাথে কাজ করে থাকেন তবে সম্ভবত আপনিই তার সাথে পরিচিত হবেন। মূলটি হ'ল ডিবাগিং। সমস্ত অজগর দেখেছে প্রিপ্রোসেসড ফাইল যার অর্থ স্ট্যাক ট্রেস ইত্যাদিতে মুদ্রিত পাঠ্যটি এতে উল্লেখ করা হবে। আপনি যদি উল্লেখযোগ্য অনুবাদ সম্পাদন করেন তবে এটি আপনার উত্স পাঠ্যের থেকে খুব আলাদা হতে পারে। উপরের উদাহরণটি লাইন সংখ্যা ইত্যাদি পরিবর্তন করে না, তাই খুব বেশি আলাদা হবে না তবে আপনি যত বেশি পরিবর্তন করবেন এটি নির্ধারণ করা তত কঠিন।


12
সুন্দর! 'ডুন করা যায় না' বলার পরিবর্তে আপনি আসলে কয়েকটি ভাল উত্তর দেন (যা 'আপনি সত্যিকার অর্থে এটি করতে চান না') এতে উজ্জীবিত হয় Up
c0m4

আমি নিশ্চিত না যে আমি প্রথম উদাহরণটি কীভাবে কাজ করে তা বুঝতে পেরেছি - myimportএমন একটি মডিউলটিতে ব্যবহারের চেষ্টা যা কেবল print 1কোডের =1 ... SyntaxError: invalid syntax
আয়ের

@ নোম: আপনার জন্য কী ব্যর্থ হচ্ছে তা নিশ্চিত নয় - এখানে আমি কেবল "1" প্রত্যাশিত হিসাবে মুদ্রিত হয়েছি। (এটি "ব্লক এম্পোর্ট টোকানাইজ" এবং "এম্পিড নতুন" ফাইল এপিপি, পাশাপাশি " b=myimport("b.py")", এবং বি.পি.-র মধ্যে রয়েছে " print 1" ঠিক আছে " " ত্রুটি থেকেও আরও কিছু রয়েছে (স্ট্যাক ট্রেস ইত্যাদি)
ব্রায়ান

3
পাইথন 3 এটিকে অনুমতি দেয় বলে মনে হয় না, যদিও উদ্দেশ্য অনুযায়ী নয়; আমি একটি বিওএম ত্রুটি পেয়েছি।
টুবু

মনে রাখবেন যে importবিল্টিনটি ব্যবহার করে __import__, সুতরাং আপনি যদি ওভাররাইট করে থাকেন ( পরিবর্তিত আমদানির প্রয়োজন মডিউলটি আমদানির আগে ), আপনার আলাদা প্রয়োজন হবে নাmyimport
টোবিয়াস কেইনজলার

21

হ্যাঁ, কিছুটা হলেও তা সম্ভব। সেখানে একটি মডিউল রয়েছে যা sys.settrace()প্রয়োগ করতে gotoএবং comefrom"কীওয়ার্ডগুলি" ব্যবহার করে:

from goto import goto, label
for i in range(1, 10):
  for j in range(1, 20):
    print i, j
    if j == 3:
      goto .end # breaking out from nested loop
label .end
print "Finished"

4
এটি যদিও আসলে নতুন সিনট্যাক্স নয় ... এটি দেখতে এটির মতো দেখাচ্ছে।
হান্স নওক

3
-1: লিঙ্কযুক্ত পৃষ্ঠাটির শিরোনামটি রয়েছে: "'গোটো' মডিউলটি এপ্রিল ফুলের রসিকতা ছিল, 1 লা এপ্রিল 2004 এ প্রকাশিত হয়েছিল। হ্যাঁ, এটি কাজ করে, তবুও এটি একটি রসিকতা। দয়া করে এটি বাস্তব কোডে ব্যবহার করবেন না!"
জিম

6
@ জিম এ -১ এ পুনর্বিবেচনা করতে পারে। এটি আপনাকে বাস্তবায়ন ব্যবস্থার প্রতি ইঙ্গিত দেয়। শুরু করার সাথে সুন্দর জিনিস।
n611x007

14

পরিবর্তন এবং সোর্স কোড (যা recompiling সংক্ষিপ্ত হয় ওপেন সোর্স সম্ভব), বেস ভাষা পরিবর্তন সত্যিই সম্ভব নয়।

এমনকি যদি আপনি উত্সটি পুনরায় সংকলন করেন তবে এটি অজগর নয়, কেবল আপনার হ্যাকড-আপ পরিবর্তিত সংস্করণ যা আপনাকে বাগগুলি প্রবর্তন না করার জন্য খুব যত্নবান হওয়া দরকার।

তবে আপনি কেন চান তা আমি নিশ্চিত নই। পাইথনের অবজেক্ট-ভিত্তিক বৈশিষ্ট্যগুলি ভাষার সাথে একইরকম ফলাফল অর্জন করা একেবারে সহজ করে তোলে।


2
আমি এক বক্তব্যে একমত নই। আপনি যদি নতুন কীওয়ার্ড যুক্ত করেন তবে আমার মনে হয় এটি এখনও পাইথন হবে। আপনি যদি বিদ্যমান কীওয়ার্ডগুলি পরিবর্তন করেন , তবে আপনি যেমন বলছেন তেমনই হ্যাকড আপ।
বিল

9
আপনি যদি নতুন কীওয়ার্ড যুক্ত করেন তবে এটি পাইথন থেকে প্রাপ্ত ভাষা হবে। আপনি কীওয়ার্ড পরিবর্তন করলে এটি পাইথন-বেমানান ভাষা।
tzot

1
আপনি কীওয়ার্ডগুলি যুক্ত করলে, আপনি "সহজ-শিখতে সহজ শেখার বাক্য গঠন" এবং "বিস্তৃত গ্রন্থাগারগুলি" এর বিন্দুটি হারিয়ে যাচ্ছেন। আমি মনে করি ভাষার বৈশিষ্ট্যগুলি প্রায় সর্বদা একটি ভুল (উদাহরণগুলির মধ্যে কোবোল, পার্ল এবং পিএইচপি অন্তর্ভুক্ত)।
এস .লট

5
নতুন কীওয়ার্ডগুলি পাইথন কোডটি ভেঙে দেয় যা সেগুলি সনাক্তকারী হিসাবে ব্যবহার করে।
আকাইহোলা

12

সাধারণ উত্তর: আপনার উত্স ফাইলগুলি প্রিপ্রোসেস করতে হবে।

আরও নির্দিষ্ট উত্তর: EasyExtend ইনস্টল করুন , এবং নিম্নলিখিত পদক্ষেপগুলি অতিক্রম করুন through

i) একটি নতুন ল্যাঙ্গলেট তৈরি করুন (এক্সটেনশন ভাষা)

import EasyExtend
EasyExtend.new_langlet("mystmts", prompt = "my> ", source_ext = "mypy")

অতিরিক্ত স্পেসিফিকেশন ছাড়াই একগুচ্ছ ফাইলগুলি ইজিএকস্ট্যান্ড / ল্যাঙ্গলেটস / মাইস্টেম্টস / এর আওতায় তৈরি করা হবে।

ii) মাইস্টেমটস / পার্সেডেফ / গ্রামার.েক্সট খুলুন এবং নিম্নলিখিত লাইনগুলি যুক্ত করুন

small_stmt: (expr_stmt | print_stmt  | del_stmt | pass_stmt | flow_stmt |
             import_stmt | global_stmt | exec_stmt | assert_stmt | my_stmt )

my_stmt: 'mystatement' expr

আপনার নতুন বিবৃতিটির বাক্য গঠনটি সংজ্ঞায়িত করতে এটি যথেষ্ট। ছোট_স্টেম্ট নন-টার্মিনাল পাইথন ব্যাকরণের অংশ এবং এটি সেই জায়গা যেখানে নতুন বিবৃতিটি হুক করা হয়েছে The পার্সার এখন নতুন বিবৃতিটি সনাক্ত করতে পারবেন অর্থাৎ এটি যুক্ত একটি উত্স ফাইল পার্স করা হবে। সংকলক যদিও এটি প্রত্যাখ্যান করবে কারণ এটি এখনও বৈধ পাইথনে রূপান্তরিত হতে পারে।

iii) এখন বিবৃতিটির শব্দার্থ যুক্ত করতে হবে। এর জন্য একটিকে msytmts / langlet.py সম্পাদনা করতে হবে এবং একটি my_stmt নোড ভিজিটর যুক্ত করতে হবে।

 def call_my_stmt(expression):
     "defines behaviour for my_stmt"
     print "my stmt called with", expression

 class LangletTransformer(Transformer):
       @transform
       def my_stmt(self, node):
           _expr = find_node(node, symbol.expr)
           return any_stmt(CST_CallFunc("call_my_stmt", [_expr]))

 __publish__ = ["call_my_stmt"]

iv) সিডি থেকে ল্যাঙ্গলেট / মাইস্টেমস এবং টাইপ করুন

python run_mystmts.py

এখন একটি সেশন শুরু হবে এবং নতুন সংজ্ঞায়িত বিবৃতি ব্যবহার করা যেতে পারে:

__________________________________________________________________________________

 mystmts

 On Python 2.5.1 (r251:54863, Apr 18 2007, 08:51:08) [MSC v.1310 32 bit (Intel)]
 __________________________________________________________________________________

 my> mystatement 40+2
 my stmt called with 42

তুচ্ছ বক্তব্য আসতে বেশ কয়েক ধাপ, ডান? এখনও এমন একটি এপিআই নেই যা ব্যাকরণ সম্পর্কে চিন্তা না করে সাধারণ জিনিসগুলি সংজ্ঞায়িত করতে দেয়। তবে ইই খুব নির্ভরযোগ্য মডুলোর কয়েকটি বাগ রয়েছে। সুতরাং এটি কেবল সময়ের বিষয় যে কোনও এপিআই উত্থিত হয় যা প্রোগ্রামারদের কেবল সুবিধাজনক ও ও প্রোগ্রামিং ব্যবহার করে ইনফিক্স অপারেটর বা ছোট স্টেটমেন্টের মতো সুবিধাজনক স্টাফ সংজ্ঞায়িত করতে দেয়। ল্যাঙ্গলেট তৈরির মাধ্যমে পাইথনে পুরো ভাষা এম্বেড করার মতো আরও জটিল জিনিসের জন্য পূর্ণ ব্যাকরণ পদ্ধতির কাছাকাছি যাওয়ার কোনও উপায় নেই।


11

কেবলমাত্র ইন্টারপ্রিটিভ মোডে নতুন বিবৃতি যুক্ত করার জন্য এখানে একটি খুব সহজ তবে কৃপণ উপায় । আমি এটি কেবল sys.displayhook ব্যবহার করে জিন টীকা সম্পাদনা করার জন্য সামান্য 1-অক্ষরের কমান্ডের জন্য ব্যবহার করছি, তবে ঠিক তাই আমি এই প্রশ্নের উত্তর দিতে পারলাম পাশাপাশি সিনট্যাক্স ত্রুটির জন্য sys.excepthook যুক্ত করেছি। পরেরটি সত্যিই কুরুচিপূর্ণ, পঠন বাফার থেকে কাঁচা কোড আনছে। সুবিধাটি হ'ল এইভাবে নতুন বিবৃতি যুক্ত করা তুচ্ছ সহজ easy


jcomeau@intrepid:~/$ cat demo.py; ./demo.py
#!/usr/bin/python -i
'load everything needed under "package", such as package.common.normalize()'
import os, sys, readline, traceback
if __name__ == '__main__':
    class t:
        @staticmethod
        def localfunction(*args):
            print 'this is a test'
            if args:
                print 'ignoring %s' % repr(args)

    def displayhook(whatever):
        if hasattr(whatever, 'localfunction'):
            return whatever.localfunction()
        else:
            print whatever

    def excepthook(exctype, value, tb):
        if exctype is SyntaxError:
            index = readline.get_current_history_length()
            item = readline.get_history_item(index)
            command = item.split()
            print 'command:', command
            if len(command[0]) == 1:
                try:
                    eval(command[0]).localfunction(*command[1:])
                except:
                    traceback.print_exception(exctype, value, tb)
        else:
            traceback.print_exception(exctype, value, tb)

    sys.displayhook = displayhook
    sys.excepthook = excepthook
>>> t
this is a test
>>> t t
command: ['t', 't']
this is a test
ignoring ('t',)
>>> ^D

4

আমি নতুন বিবৃতি যুক্ত করার জন্য একটি গাইড পেয়েছি:

https://troeger.eu/files/teaching/pythonvm08lab.pdf

মূলত, নতুন বিবৃতি যুক্ত করতে, আপনাকে সম্পাদনা করতে হবে Python/ast.c(অন্যান্য জিনিসের মধ্যে) এবং পাইথন বাইনারিটি পুনরায় কম্পাইল করতে হবে।

যদিও এটি সম্ভব, না। আপনি ফাংশন এবং ক্লাসের মাধ্যমে প্রায় সবকিছু অর্জন করতে পারেন (যার ফলে লোকেরা কেবল আপনার স্ক্রিপ্টটি চালানোর জন্য অজগরটিকে পুনরায় সংকলন করতে পারে না))


পিডিএফ-এর আসল লিঙ্কটি - যে "স্বায়ত্তশাসন" ভেঙে গেছে এবং Godশ্বরের জন্য এটি এখন দীর্ঘই
জেডএক্সএক্স

3

ইজি এক্সটেন্ড ব্যবহার করে এটি করা সম্ভব :

ইজিএকসেট (ইই) হ'ল একটি প্রিপ্রোসেসর জেনারেটর এবং মেটাপ্রোগ্র্যামিং ফ্রেমওয়ার্ক যা খাঁটি পাইথনে লেখা এবং সিপিথনের সাথে সংহত। ইজিএকসেটেন্ডের মূল উদ্দেশ্য হ'ল এক্সটেনশন ভাষা তৈরি করা অর্থাত পাইথনে কাস্টম বাক্য গঠন এবং শব্দার্থবিজ্ঞান যুক্ত করা।


1
সেই লিঙ্কটি অনুসরণ করে এখন একটি পৃষ্ঠা দেওয়া হয়েছে: "ইজি এক্সটেন্ড মারা গেছে who যারা ইইতে আগ্রহী তাদের জন্য ল্যাংস্কেপ ডিফারেন্ট নাম, সম্পূর্ণ পুনরায় নকশা, একই যাত্রা নামে একটি উত্তরসূরি প্রকল্প রয়েছে" " যেহেতু এই তথ্য পৃষ্ঠাটি মারা যেতে পারে এমন আশঙ্কা রয়েছে, তাই উত্তরটি আপডেট করা ভাল ধারণা।
celtschk

3

এটি ভাষা সিনট্যাক্সে ঠিক নতুন বক্তব্য যোগ করছে না, তবে ম্যাক্রোগুলি একটি শক্তিশালী সরঞ্জাম: https://github.com/lihaoyi/macropy


1

দোভাষী সংশোধন ছাড়া না। আমি জানি গত কয়েক বছরে প্রচুর ভাষাগুলি "এক্সটেনসিবল" হিসাবে বর্ণিত হয়েছে, তবে আপনি যেভাবে বর্ণনা করছেন তেমন নয়। আপনি ফাংশন এবং ক্লাস যুক্ত করে পাইথন প্রসারিত করেছেন।


1

লগিক্স নামে অজগর ভিত্তিক একটি ভাষা রয়েছে যার সাহায্যে আপনি এই জাতীয় জিনিসগুলি করতে পারেন। এটি একটি সময় জন্য উন্নয়ন অধীনে হয়েছে না, কিন্তু অতিরিক্ত বৈশিষ্ট্যগুলিও উপস্থিত রয়েছে যে আপনার জন্য জিজ্ঞাসা Do কাজ সর্বশেষ সংস্করণ সহ।


মনে হচ্ছে আকর্ষণীয়, তবে মনে হচ্ছে এটি ২০০৯ সালের দিকে মারা গিয়েছিল: web.archive.org/web/20090107014050/http://livelogix.net/logix
টোবিয়াস কেইনজলার

1

কিছু জিনিস সাজসজ্জা দিয়ে করা যেতে পারে। ধরা যাক ধরুন, পাইথনের কোনও withবক্তব্য ছিল না । তারপরে আমরা এর মতো অনুরূপ আচরণ বাস্তবায়ন করতে পারি:

# ====== Implementation of "mywith" decorator ======

def mywith(stream):
    def decorator(function):
        try: function(stream)
        finally: stream.close()
    return decorator

# ====== Using the decorator ======

@mywith(open("test.py","r"))
def _(infile):
    for l in infile.readlines():
        print(">>", l.rstrip())

এটি এখানে যেমন করা হয়েছে তেমন একটি অশুচি সমাধান। বিশেষ করে আচরণ যেখানে প্রসাধক ফাংশন কল এবং সেট _করার Noneঅপ্রত্যাশিত নয়। স্পষ্টতার জন্য: এই সাজসজ্জা লেখার সমতুল্য

def _(infile): ...
_ = mywith(open(...))(_) # mywith returns None.

এবং সাজসজ্জার সাধারণত ফাংশন সম্পাদন করে না, পরিবর্তিত হবে বলে আশা করা হয়।

আমি স্ক্রিপ্টে এর আগে এমন পদ্ধতি ব্যবহার করেছি যেখানে বেশ কয়েকটি ফাংশনের জন্য আমাকে অস্থায়ীভাবে ওয়ার্কিং ডিরেক্টরি সেট করতে হয়েছিল।


0

দশ বছর আগে আপনি পারবেন না এবং আমি সন্দেহ করেছি যে এটি বদলে গেছে। যাইহোক, যদি আপনি অজগরটি পুনরায় সংকলনের জন্য প্রস্তুত হন, তবে সিনট্যাক্সটি ফিরে পরিবর্তন করা এতটা কঠিন ছিল না এবং আমি সন্দেহ করি যে এটিও পরিবর্তিত হয়েছে।

আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.