exec()在函数python3.x中不起作用

时间:2016-12-12 11:48:15

标签: python python-3.x exec

我正在尝试运行此代码,但似乎exec()没有在函数内执行字符串:

def abc(xyz):
    for i in fn_lst:
        s = 'temp=' + i + '(xyz)'
        exec(s)
        print (temp)

abc('avdfbafadnf')

我收到的错误:

NameError                                 Traceback (most recent call last)
<ipython-input-23-099995c31c78> in <module>()
----> 1 abc('avdfbafadnf')

<ipython-input-21-80dc547cb34f> in abc(xyz)
      4         s = 'temp=' + i + '(word)'
      5         exec(s)
----> 6         print (temp)

NameError: name 'temp' is not defined

fn_lst是一个函数名列表,即:['has_at', 'has_num' ...]

如果可能的话,请让我知道exec()的替代方案。

4 个答案:

答案 0 :(得分:6)

我没有足够的声望点来添加评论,但我想提一下 DrM 之前的回答不起作用(在函数内):

def test():
    exec( 'a = 3', globals(), locals() )
    print(a)
test()

此代码在 Python 3 中出现错误:

NameError: name 'a' is not defined

我使用其他论坛中建议的 compile 函数尝试了一些方法,但它们仍然对我不起作用(至少在我看到提到的选项时)。

根据我的研究,这是我见过的最接近的代码:

def test():
    lcls = locals()
    exec( 'a = 3', globals(), lcls )
    a = lcls["a"]
    print(f'a is {a}')
test()

它成功打印:

a is 3

我认为这是一个很重要的话题。有时,当您使用符号代数库(如 Sympy)时,通过 exec 函数定义变量对于科学计算非常方便。

我希望有人知道这个问题的好答案。

答案 1 :(得分:3)

要通过传递给exec()的字符串设置变量,在调用之外可用,请使用exec(),如下所示:

 //sample xml : 

    <?xml version="1.0" encoding="utf-8"?>
    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:tools="http://schemas.android.com/tools"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical"
        android:layoutDirection="rtl"
        tools:context=".SampleActivity">
        <android.support.design.widget.TabLayout
            android:id="@+id/tabs"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"/>
        <com.booking.rtlviewpager.RtlViewPager
            android:id="@+id/pager"
            android:layout_width="match_parent"
            android:layout_height="match_parent"/>
    </LinearLayout>


    // fragment_main xml : 

    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:background="#00000000"
        android:orientation="vertical"
        >
        <TextView
            android:id="@+id/title"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_gravity="center"
            android:layout_marginTop="44dp"
            android:textDirection="anyRtl"
            android:textColor="#ffffff"
            android:textSize="60dp" />

    </LinearLayout>


    // SampleActivity class : 


    import android.graphics.Color;
    import android.os.Bundle;
    import android.support.design.widget.TabLayout;
    import android.support.v4.app.Fragment;
    import android.support.v4.app.FragmentManager;
    import android.support.v4.app.FragmentPagerAdapter;
    import android.support.v4.view.PagerAdapter;
    import android.support.v4.view.ViewPager;
    import android.support.v7.app.AppCompatActivity;
    import android.view.Gravity;
    import android.view.View;
    import android.view.ViewGroup;
    import android.widget.TextView;

    import static android.view.ViewGroup.LayoutParams.MATCH_PARENT;



    public class SampleActivity extends AppCompatActivity {
        @Override
        protected void onCreate(Bundle savedInstanceState){
            super.onCreate(savedInstanceState);
            setContentView(R.layout.sample);
            TabLayout tabs = (TabLayout) findViewById(R.id.tabs);
            ViewPager viewPager = (ViewPager) findViewById(R.id.pager);
            //TextViewPagerAdapter adapter = new TextViewPagerAdapter(7);
            MyPagerAdapter adapter = new MyPagerAdapter(getSupportFragmentManager(), new String[]{"الاحد ","الاثنين ","الثلاثاء ","الاربعاء"});
            viewPager.setAdapter(adapter);
            tabs.setupWithViewPager(viewPager);
        }







        public class MyPagerAdapter extends FragmentPagerAdapter{

            private String [] strings;
            public MyPagerAdapter(FragmentManager fm  , String []stringstodisplay) {
                super(fm);
                this.strings = stringstodisplay;
            }




            @Override
            public Fragment getItem(int pos){
                return FragmentViewPager.newInstance(strings[pos]);
            }


            @Override
            public int getCount() {
                return strings.length;
            }
        }


        static class TextViewPagerAdapter extends PagerAdapter {

            private int pages;


            TextViewPagerAdapter(int pages) {

                this.pages = pages;
            }

            @Override
            public int getCount() {
                return pages;
            }

            @Override
            public Object instantiateItem(final ViewGroup container, int position) {

                // Text Page
                final String item = "" + position;
                final TextView text = new TextView(container.getContext());
                text.setGravity(Gravity.CENTER);
                text.setBackgroundColor(Color.WHITE);
                text.setTextColor(Color.BLACK);
                text.setTextSize(30);
                text.setText(item);
                container.addView(text, MATCH_PARENT, MATCH_PARENT);
                text.setTag(item);
                return item;
            }



            @Override
            public CharSequence getPageTitle(int position) {


                return String.valueOf(position);
            }



            @Override
            public boolean isViewFromObject(View view, Object object) {
                return object.equals(view.getTag());
            }


            @Override
            public void destroyItem(ViewGroup container, int position, Object object) {


                container.removeView(container.findViewWithTag(object));
            }


            // End  -------------- ;

        }
    }

    // FragmentViewPager class : 

    import android.os.Bundle;
    import android.view.LayoutInflater;
    import android.view.View;
    import android.view.ViewGroup;
    import android.widget.ImageView;
    import android.widget.TextView;



    public class FragmentViewPager extends android.support.v4.app.Fragment {

        // ArabicUtilities.reshapeSentence(

        @Override
        public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
            View v = inflater.inflate(R.layout.fragment_main, container, false);
            TextView tv = (TextView) v.findViewById(R.id.title);
            tv.setText(getArguments().getString("text"));
            //tv.setTextDirection(View.TEXT_DIRECTION_ANY_RTL);
            //ImageView imageView = (ImageView) v.findViewById(R.id.image);
            //imageView.setBackgroundResource(getArguments().getInt("img"));
            return v;
        }



        public static FragmentViewPager newInstance(String text) {
            FragmentViewPager f = new FragmentViewPager();
            Bundle b = new Bundle();
            b.putString("text", text);
           // b.putInt("img", image);
            f.setArguments(b);
            return f;
        }
    }

例如,

exec( a_string, locals(), globals() )

将打印以下结果:

exec( 'a = 3', locals(), globals() )

print( a )

注意:在这个例子中,单独使用locals()就足够了,即省略globals()。两者都包括在这里,以说明更一般的情况。 locals()和/或globals()的使用是更大主题的一部分,称为“Scope”。您可以在Python Textbook - Scope

了解详情

答案 2 :(得分:3)

在这个问题上花了这么多时间做hit和trial之后,我可以说像这样使用exec在函数内部没有任何问题,否则它会抛出错误。 我已经对函数和变量进行了测试。

def main():
  x = "def y():\n\treturn('This will work')"
  #pass only globals() not locals()
  exec(x,globals())
  print(y())
  
main()

def test():
    #pass only globals() not locals()
    exec( 'a = 3', globals())
    print(a)
test()

这是在 W3School's online interpreter 上工作的屏幕截图(您可以自己复制/粘贴并在此处测试) enter image description here

答案 3 :(得分:0)

不要将exec与函数名一起使用,只需将函数对象保留在列表中:

fn_lst = [has_at, has_num, ...]

直接执行调用

def abc(xyz):
    for i in fn_lst:
        temp= i(xyz)
        print(temp)