精华内容
下载资源
问答
  • 【Python】如何将字符串作为变量名

    万次阅读 多人点赞 2016-04-11 15:37:47
    就像JS一样,当python在使用变量时,会按照下面的步骤去搜索:   函数或类的局部变量。 全局变量。 内置变量。   以上三个步骤,其中一步骤找到对应的变量,就不会再往下找。如果在这三个步骤都...

    一共三种方法:

     

    >>> var = "This is a string"
    >>> varName = 'var'
    >>> s= locals()[varName]
    >>> s
    'This is a string'
    >>> s2=vars()[varName]
    >>> s2
    'This is a string'
    >>> s3=eval(varName)
    >>> s3
    'This is a string'

    1. locals()

     

    locals是python的内置函数,他可以以字典的方式去访问局部和全局变量。

    python里面用名字空间记录着变量,就像javascript的window一样,他记录着各种全局变量。

    每个模块,每个函数都有自己的名字空间,记录着变量,常量,类的命名和值。

    就像JS一样,当python在使用变量时,会按照下面的步骤去搜索:

     

    • 函数或类的局部变量。
    • 全局变量。
    • 内置变量。

     

    以上三个步骤,其中一步骤找到对应的变量,就不会再往下找。如果在这三个步骤都找不到,就会抛出异常。

    locals与globals的区别

     

    • locals()是只读的。globals()不是。这里说的只读,是值对于原有变量的只读。其实还可以对locals()赋值的。
    • globals返回的是当前模块的全局变量 locals返回的是局部变量。注意,locals返回的是当前所在最小命名空间的局部变量的一个拷贝

    体检locals

    list1 = [1,2,3]
    locals()
    
    # 在全局中使用locals,会打印出list1和__builtins__、__name__、__doc__、__package__
    复制代码
    def foo(args):
        x=1
        print locals()
    
    foo(123)
    
    #将会得到 {'arg':123,'x':1}

    2. vars()

    本函数是实现返回对象object的属性和属性值的字典对象。如果默认不输入参数,就打印当前调用位置的属性和属性值,相当于locals()的功能。如果有参数输入,就只打印这个参数相应的属性和属性值。

    #vars()  
      
    print(vars())  
      
    class Foo:  
        a = 1  
    print(vars(Foo))  
      
    foo = Foo()  
    print(vars(foo)) 

    3. eval()

    eval()函数十分强大,官方demo解释为:将字符串str当成有效的表达式来求值并返回计算结果。

    结合math当成一个计算器很好用。

    其他用法,可以把list,tuple,dict和string相互转化。见下例子:

     

    a = "[[1,2], [3,4], [5,6], [7,8], [9,0]]"
    b = eval(a)
    b
    Out[3]: [[1, 2], [3, 4], [5, 6], [7, 8], [9, 0]]
    type(b)
    Out[4]: list
    a = "{1: 'a', 2: 'b'}"
    b = eval(a)
    b
    Out[7]: {1: 'a', 2: 'b'}
    type(b)
    Out[8]: dict
    a = "([1,2], [3,4], [5,6], [7,8], (9,0))"
    b = eval(a)
    b
    Out[11]: ([1, 2], [3, 4], [5, 6], [7, 8], (9, 0))

    强大的函数有代价。安全性是其最大的缺点。

     

    想一想这种使用环境:需要用户输入一个表达式,并求值。

    如果用户恶意输入,例如:

    __import__('os').system('dir')

    那么eval()之后,你会发现,当前目录文件都会展现在用户前面。

    那么继续输入:

    open('文件名').read()

    代码都给人看了。获取完毕,一条删除命令,文件消失。哭吧!

    怎么避免安全问题?

    (1) 自行写检查函数;

    (2) 使用ast.literal_eval

    eval() 和exec()

    • 区别是eval()有返回值 

    1

    2

    3

    4

    5

    def test1():

        print "Test1 Excuted!"

        return True

    ret = eval ("test1()")

    print ret

    • 结果如下

    1

    2

    3

    >>> 

    Test1 Excuted!

    True

    • 而exec()只执行,并无返回值。

    1

    2

    3

    4

    def test2():

        print "Test2 Excuted!"

        return True

    exec("test2()")

    • 结果如下

    1

    2

    3

    >>> 

    Test2 Excuted!

    >>>

    • 如果要将exec()赋值,会有以下语法错误!

    1

    ret = exec("test2()")

     

     

     

    展开全文
  • 有了前面两篇的基础,下面正式开扒变量名和内存的关系,先看一段大家很熟悉的代码: int i;  scanf_s("%d", &i); int i;,在这一句就为i分配了内存(但尚未对这块内存进行初始化),所以可以通过&i直接使用这块内存。...

    有了前面两篇的基础,下面正式开扒变量名和内存的关系,先看一段大家很熟悉的代码:

      int i;
      scanf_s("%d", &i);

    int i;,在这一句就为i分配了内存(但尚未对这块内存进行初始化),所以可以通过&i直接使用这块内存。赋值就更不用说啦,i = 3;。

    变量名i,是为方便编程人员使用,是这块内存的别名,指代到块内存,对编程人员i代表这块内存中存储的值(实际上是i指到这个内存,然后取值)。通常我们都是通过变量名来使用已知的内存的。

    i代表取(这块内存中存储的)值,而&i代表取(这块内存的)址。程序本身是不为i这个变量名分配空间的。在最终的机器代码中,是不会出现变量名的,这一点在分析反汇编语言时可以看出(命令:dumpbin /disasm xx.obj >xx_disasm.asm可以查看反汇编语言)。那么编译器是如何处理变量名的呢,变量名会存储在符号表中,并将符号表中的索引对应到实际物理空间(地址)上去,当调用这个变量时,查找符号表就可以找到对应的地址并取值了。

     

    上面分析的是基本数据类型(如int、char等)的变量名。C中除了变量名之外,还有函数名、常量名、指针名、数组名、结构名等。和变量名不同,这些标识符都是直接对应着地址的。基本数据类型的变量,和地址的对应关系需要取址符&才能得到地址,而其余的这些,名字本身就对应着地址。

    例如char *pc = “se”;,就是将字符串常量”se”的首地址(位于常量存储区)赋值给了字符指针pc。这也就解释了为什么不需要为pc分配地址就可以为其赋值,而不会遇到类似下面代码所带来的野指针问题:

      int *pi;
      *pi = 1;

    int *pi句,是为pi分配空间,而不是开辟pi所指向的空间。

     

    下面分别来看不同类型变量的变量名和内存见的关系:

    先看C中的常量:

    C对常量是怎么处理的呢?比如上面的i = 3;中的常量3,存储常量3的地址并不是随机分配的,是在程序中的数据段中(.data?这个我也还不是很确定,希望知道的前辈们给个指导)也就是程序本身并不为3分配内存,而是直接写入指令。3是数字常量,对于字符常量和字符串常量,又分别是怎么处理的呢?

    字符常量和数字常量是一样的处理方式,都是类似汇编中的立即数,直接写入指令;

    而字符串常量,则是存储在常量存储区,可以使用&(“string”)取得具体地址。也就是字符串常量名字本身指代着地址,只是不能直接操作(和int i中的i相同)。

     

    再看各种类型的变量名,c中的数据类型除常量之外大致5种:

    基本数据类型:int、float、double、char等:

    对各基本数据类型的变量名及其声明时的处理方式都是一样的,声明时即分配内存,并使用变量名直接操作这段内存;使用取地址符号&取得地址的数字表示,至于声明时要不要做初始化,要看是不是全局变量或者 static变量了。

    这类变量名指向一个地址空间,但不能直接当做地址使用,而是通过取址符&操作其地址。

     

    构造数据类型:数组、结构、联合:

    1)         数组

    数组在声明时,即分配了空间:

       int a[5];

    一旦声明a[5],相当于有a、a[0]、a[1]、a[2]、a[3]、a[4]这6个变量名。a[i]的指代方式和普通的变量名int i相同,指到一个对应的内存空间;关键是变量名a,本身就可以做地址用。我们知道a是数组名,但a并不代表整个数组的地址,而是指向数组首元素的地址(虽然在数值上是相同的,下面会有详细解释),所以可以有 int *p = a;。那么&a又怎么解释呢?对于int i而言,i代表一个空间,&i表示i所代表的空间地址;那么&a应该也是表示a所代表的地址了,也就是整个数组的地址。

    a、&a和&a[0]同代表地址,且由于数组是顺序存储,所以a、&a和&a[0]所表示的地址在数据上是相同的,但是实际的指代意义却是不同的:

    • a是个int*类型的数据,相当于&(*a),是指向数组首元素的地址;
    • &a指代整个数组,是个int(*)[]类型的数据,是指针数组的地址;
    • &a[0]则是仅指代一个存储int的空间,是int*类型的数据。

    也就是数组名,本身可以作为地址使用,指代该结构的首元素的地址。

    2)         结构

    结构在声明的时候,就分配了空间。结构体和数组不同,结构体类型的变量名并不能直接当作地址使用,这一点和基本数据类型相同。需要对结构体名使用取址符&才能进行地址操作,并且取址所得到地址代表的是指向结构体的指针,只是在数据上和结构体中的首元素地址相同。

    对于结构体中的各个元素,其名称的指代关系和其数据类型相同,并不因为是结构体的元素而受到影响。具体见下面代码:

    struct stu{
    
             int age;
             char sex;
             char* name;
             int score[5];
    }; 
    
    int main()
    {
             int i;
             struct stu st1;              //st1是 结构体stu类型
             printf("%d\n", &st1);        //&st1是 stu*类型
             printf("%d\n", &st1.age);    //&st1.age是 int*类型,st1.age就是个int型,名字指向地址,但不能直接作地址
    printf("%d\n", &st1.sex); //&st1.sex是 char*类型,名字解析同上 printf("%d\n", &st1.name); //&st1.name是 char**类型,st1.name是char*类型 printf("%d\n", st1.score); // st1.score是个数组类型,名字代表数组中首元素的地址 return 0; }

     

    3)         联合:联合是特殊的结构体,为节省空间,在其各元素依次存储,各元素的首地址均相对变量的基地址偏移为0,具体各变量名的分析和结构体同。

     

    指针类型

    声明一个指针类型 int *p;,则是为存储指针p分配空间,而并不会为p所指向的内存做任何动作,这就是野指针的原因。如下代码,p就是一个未指向任何已知内存的指针,为*p赋值,自然会出现错误:

      int *p;
      *p = 1;

    指针中,char *是个很特殊的指针。一般的指针,仅指向一个所定义类型的内存,而char *则可以指向一个字符串,之所以可以实现这个功能是字符串结尾符’\0’的存在标识了字符串的结束。如下的代码,就是将pc指向了“string”所指代的常量存储区地址。

      char *pc = “string”;

    这也是char *pc = “string”合法,而int *p =1不合法的原因:"string"本身即代表了它的存储地址,而整型常量1仅仅是个操作数,并不是地址,如果希望使用数据为指针(指向的地址)赋值,可以使用一个强制转换 int*p = (int*)1,只是这样如果不加以检查的话,写出来的代码会存在安全隐患。因此,不管指针变量是全局的还是局部的、静态的还是非静态的,都应该在声明它的同时进行初始化,要么赋予一个有效的地址,要么赋予NULL。

    另外,声明一个指针,只是在栈区为指针本身的存储分配了地址,而不限制指针所指向的内存到底是在栈区、还是在堆区、还是在常量存储区。这也就造成了 函数调用返回值 会因实现不同而有不同意义,是函数调用结束后返回值有效性不同的原因。详见《从字符串截取说指针和地址》

     

    空类型

    C中有void关键字,但其实C中是并没有空类型的。比如我们不能做如下定义:

        void a;

    因为C、C++是静态类型的语言,定义变量就会分配内存。然而,不同类型的变量所占内存不同,如果定义一个任意类型的变量,就无法为其分配内存。所以,C、C++中没有任意类型的变量。

    但是定义void *p;是合法的,void *所定义的p表示以指针,所指向的类型未定。因为void *p;声明是为指针p分配了空间,无论指针指向什么类型,存储指针所需的空间的固定的,所以不存在因为所需空间大小而无法为p分配空间的问题。

    但void *p的使用也是很受限制的,由于不知道其指向的数据类型,所以是不能对p进行自增操作的;void的主要作用有两点,一个是限制函数的返回值,一个是限制函数的参数类型;void *则常用于指针的类型转换。如下代码:

      int *pi;
      float *pf;

    如果想将pi指向pf所指向的内存空间,就必须进行类型转换:pi = (int *)pf;。

    而如果是将pi换成void *p,就不需要转换,可以直接为指针赋值。这样的直接赋值,只能是将一个已知类型的指针赋值给void *p,而不能是将void *p未加强制转换地赋值给一个已知类型的指针,如:

        void *p;
        int *pi;
        float *pf;
        p = pf;   // pf = p;就是非法的,不能将 "void *" 类型的值分配到 "float *" 类型的实体
        p = pi;

    但需要注意的是,即使进行了转换,p仍然是个void*类型的指针,不能对其进行sizeof(p)等涉及所指类型的操作,同样地p也不能直接用于具体数据类型的操作。如下面的代码中*p = 1.73; 和printf("%f", *p)都是非法的:

        void *p;
        float *pf;
        p = pf;
    *p = 1.73; //*pf = 1.73;合法 printf("%f", *p); //printf("%f", *pf); 合法

    这样说来,void *的意义何在呢?可以使用强制类型转换使用void *p作为中介,见下面的代码:

      float *pf;
      void *p;
      float f=1.6;
      p = (void*)&f;
      pf = (float*)p;

    这样,float *pf就指向了float f所在的地址,但注意p依然不能直接使用。这个例子,只是为我们展示了void *有这样的功能,但平常代码中很少这样无意义地转换,更多地是将void *作为函数参数,这样就可以接受任意类型的指针了,典型的如内存操作函数memcpy和memset的函数,其原型分别为:

      void * memcpy(void *dest, const void *src, size_t len);
      void * memset ( void * buffer, int c, size_t num );

    也可以编写自己的将void *作为函数参数的函数,由于char是C中最小长度的变量,其它任何变量的长度都是它的整数倍。可以使用char*作为中转,详见下面的函数实现:

    void swap(void *pvData1, void *pvData2, int iDataSize)
    {
        unsigned char  *pcData1 = NULL;
        unsigned char  *pcData2 = NULL;
        unsigned char  ucTmp1;
        pcData1 = (unsigned char *)pvData1;
        pcData2 = (unsigned char *)pvData2;   
    
        do{
            ucTmp1       = *pcData1;
            *pcData1     = *pcData2;
            *pcData2     = ucTmp1;
            pcData1++;
    
            pcData2++;
        } while (--iDataSize > 0);
    }
    
    
    int main()
    {
             float fa = 1.23, fb = 2.32;
             float *f1=&fa, *f2=&fb;
             int iDataSize = sizeof(float)/sizeof(char);
    swap(f1, f2, iDataSize);
    return 0; }

     

    NULL

    C中对NULL的预定义有两个:

      #define NULL    0
      #define NULL    ((void *)0)

    并且标准C规定,在初始化、赋值或比较时,如果一边是变量或指针类型的表达式,则编译器可以确定另一边的常数0为空指针,并生成正确的空指针值。即在指针上下文中“值为0的整型常量表达式”在编译时转换为空指针。那么也就是上面的两个的定义在指针上下文中是一致的了。

    我们经常在声明一个指针时,为避免野指针的情况常用的int *pi = NULL;中的NULL,是会被自动转换为(void *)0的。所以下面的代码也是合法的:

    int *pi = 0;
    if(pi == 0){
     …… 
    }

     

    函数类型 和 函数指针

    尽管函数并不是变量,但它在内存中仍有其物理地址。每个函数都有一个入口地址,由函数名指向这个入口地址,函数名相当于一个指向其函数入口的指针常量。

    可以将函数名赋值给一个指针,使该指针指向这个函数的入口,即是函数指针

    这里注意和指针函数区分开来:

    指针函数是一个返回指针的函数,指针函数具体定义方式:

    char *Convert(char *pName , int length);

    函数指针的定义要和具体所指向的函数的形式一致,如对函数int Max(int a, int b)定义一个函数指针:

      int (*pMax)(int a, int b);
      pMax = Max;

    int (*pMax)(int a, int b)句中,函数指针pMax外的括号一定要带上[s1] ,因为“()”的优先级高于“*”,如果无括号,就变成了int *pMax(int a, int b)的形式,变成了一个函数(指针函数)的声明了。pMax=Max句将代表函数int Max(int a, int b)入口地址的其函数名Max,赋值给了指向同类型函数的指针pMax。这样pMax就和Max有相同的指代作用,并且pMax还可以指向与int Max(int a, int b)同参同返回值的函数。

      int Max(int a, int b);
      int Min(int a, int b);
      
    int (*p)(int a, int b); int max, min; p = Max; max = (*p)(3, 5); //进行调用时,也要记得带括号(*p) p = Min; min = (*p)(3, 5)

    执行中对指针p指向进行截图:

     

    最后需要注意的是,由于函数在内存中的分布方式并不是齐整的,所以函数指针并没有++自增运算和—自减运算。


     [s1]

    通过括号强行将pMax首先与“*”结合,也就意味着,pMax是一个指针;接着与后面的“()”结合,说明该指针指向的是一个函数,然后再与前面的int结合,也就是说,该函数的返回值是int。由此可见,pfun是一个指向返回值为int的函数的指针。


    <script type="text/javascript" src="http://pagead2.googlesyndication.com/pagead/show_ads.js"></script>
    展开全文
  • Python中如何将字符串作为变量名

    千次阅读 2020-01-11 15:33:12
    通过配置文件获取服务器上配置的服务及运行端口号,编写python脚本检测服务上服务是否在运行? #!/usr/bin/env python # -*- coding:utf-8 -*- # fileName: config.py # 服务配置 class config: serviceList = '...

    应用场景描述:

    通过配置文件获取服务器上配置的服务名及运行端口号,编写python脚本检测服务上服务是否在运行?

    #!/usr/bin/env python
    # -*- coding:utf-8 -*-
    # fileName: config.py
    # 服务配置
    class config:
        serviceList = 'service1,service2,service3'
        service1 = '服务1'
        service1Port = 8001
        service2 = '服务2'
        service2Port = 8002
        service3 = '服务3'
        service3Port = 8003
    

    '''
    遇到问题没人解答?小编创建了一个Python学习交流QQ群:579817333 
    寻找有志同道合的小伙伴,互帮互助,群里还有不错的视频学习教程和PDF电子书!
    '''
    #!/usr/bin/env python
    # -*- coding:utf-8 -*-
    # fileName: envCheck.py
    import socket
    from config import config
    
    config = config
    serviceList = config.serviceList
    
    # 判断某端口服务是否运行
    def portCheck(host, port):
        sk = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        sk.settimeout(1)
        try:
            sk.connect((host, port))
            # print '在服务器 %s 上服务端口 %d 的服务正在运行!' % (host, port)
            return True
        except Exception:
            # print '在服务器 %s 上服务端口 %d 的服务未运行!' % (host, port)
            return False
        sk.close()
    
    # 基础服务运行状态检测
    def envCheck():
        for serviceName in serviceList.split(','):
            host = '127.0.0.1'  # 必须为字符串格式,如:'127.0.0.1'
            servicePort = ''.join(['config.',serviceName,'Port'])
            port = eval(servicePort)  # 端口必须为数字
            if portCheck(host, port):
                print u"在%s服务器上服务端口为 %s 的 %s 服务正在运行......" % (host, port, serviceName)
            else:
                print u"在%s服务器上服务端口为 %s 的 %s 服务未运行!" % (host, port, serviceName)
    
    
    if __name__ == "__main__":
        envCheck()
    

    这个里面使用到了将字符串作为变量名的方式从配置中获取服务端口,下面我们具体看下除了这种方式以外还有哪些方式可以实现

    一共有三种实现方法:

    '''
    遇到问题没人解答?小编创建了一个Python学习交流QQ群:579817333 
    寻找有志同道合的小伙伴,互帮互助,群里还有不错的视频学习教程和PDF电子书!
    '''
    # 方法一:
    >> servicePort = ''.join(['config.',serviceName,'Port'])
    >>port = locals()[servicePort)] 
    >>print "%s:%d" %(serviceName, port)
    # 输出结果
    service1Port:8001
    service2Port:8002
    service3Port:8003
    
    # 方法二:
    >> servicePort = ''.join(['config.',serviceName,'Port'])
    >>port = vars()[servicePort)] 
    >>print "%s:%d" %(serviceName, port)
    # 输出结果
    service1Port:8001
    service2Port:8002
    service3Port:8003
    
    # 方法三:
    >> servicePort = ''.join(['config.',serviceName,'Port'])
    >>port = eval(servicePort) 
    >>print "%s:%d" %(serviceName, port)
    # 输出结果
    service1Port:8001
    service2Port:8002
    service3Port:8003
    

    1. locals()

    locals是python的内置函数,他可以以字典的方式去访问局部和全局变量。

    python里面用名字空间记录着变量,就像javascript的window一样,他记录着各种全局变量。

    每个模块,每个函数都有自己的名字空间,记录着变量,常量,类的命名和值。

    就像JS一样,当python在使用变量时,会按照下面的步骤去搜索:

    • 函数或类的局部变量。
    • 全局变量。
    • 内置变量。

    以上三个步骤,其中一步骤找到对应的变量,就不会再往下找。如果在这三个步骤都找不到,就会抛出异常。

    locals与globals的区别

    • locals()是只读的。globals()不是。这里说的只读,是值对于原有变量的只读。其实还可以对locals()赋值的。
    • globals返回的是当前模块的全局变量 locals返回的是局部变量。注意,locals返回的是当前所在最小命名空间的局部变量的一个拷贝。

    体检locals

    list1 = [1,2,3]  
    locals()  
      
    # 在全局中使用locals,会打印出list1和__builtins__、__name__、__doc__、__package__  
    复制代码  
    def foo(args):  
        x=1  
        print locals()  
      
    foo(123)  
      
    #将会得到 {'arg':123,'x':1}
    

    2. vars()

    本函数是实现返回对象object的属性和属性值的字典对象。如果默认不输入参数,就打印当前调用位置的属性和属性值,相当于locals()的功能。如果有参数输入,就只打印这个参数相应的属性和属性值。

    '''
    遇到问题没人解答?小编创建了一个Python学习交流QQ群:579817333 
    寻找有志同道合的小伙伴,互帮互助,群里还有不错的视频学习教程和PDF电子书!
    '''
    #vars()    
        
    print(vars())    
        
    class Foo:    
        a = 1    
    print(vars(Foo))    
        
    foo = Foo()    
    print(vars(foo))
    

    3. eval()

    eval()函数十分强大,官方demo解释为:将字符串str当成有效的表达式来求值并返回计算结果。

    结合math当成一个计算器很好用。

    其他用法,可以把list,tuple,dict和string相互转化。见下例子:

    a = "[[1,2], [3,4], [5,6], [7,8], [9,0]]"  
    b = eval(a)  
    b  
    Out[3]: [[1, 2], [3, 4], [5, 6], [7, 8], [9, 0]]  
    type(b)  
    Out[4]: list  
    a = "{1: 'a', 2: 'b'}"  
    b = eval(a)  
    b  
    Out[7]: {1: 'a', 2: 'b'}  
    type(b)  
    Out[8]: dict  
    a = "([1,2], [3,4], [5,6], [7,8], (9,0))"  
    b = eval(a)  
    b  
    Out[11]: ([1, 2], [3, 4], [5, 6], [7, 8], (9, 0))
    

    强大的函数有代价。安全性是其最大的缺点。

    想一想这种使用环境:需要用户输入一个表达式,并求值。

    如果用户恶意输入,例如:

    __ import__('os').system('dir')
    

    那么eval()之后,你会发现,当前目录文件都会展现在用户前面。

    那么继续输入:

    open('文件名').read()
    

    代码都给人看了。获取完毕,一条删除命令,文件消失。哭吧!

    怎么避免安全问题?

    (1) 自行写检查函数;

    (2) 使用ast.literal_eval

    展开全文
  • Python:如何将字符串作为变量名

    千次阅读 2018-03-04 16:53:44
    就像JS一样,当python在使用变量时,会按照下面的步骤去搜索:   函数或类的局部变量。 全局变量。 内置变量。   以上三个步骤,其中一步骤找到对应的变量,就不会再往下找。如果在这三个步骤都找不到,就会抛出...

    转自:http://blog.csdn.net/ztf312/article/details/51122027

    一共三种方法:

     

    [python] view plain copy
     
    1. >>> var = "This is a string"  
    2. >>> varName = 'var'  
    3. >>> s= locals()[varName]  
    4. >>> s  
    5. 'This is a string'  
    6. >>> s2=vars()[varName]  
    7. >>> s2  
    8. 'This is a string'  
    9. >>> s3=eval(varName)  
    10. >>> s3  
    11. 'This is a string'  

    1. locals()

     

    locals是python的内置函数,他可以以字典的方式去访问局部和全局变量。

    python里面用名字空间记录着变量,就像javascript的window一样,他记录着各种全局变量。

    每个模块,每个函数都有自己的名字空间,记录着变量,常量,类的命名和值。

    就像JS一样,当python在使用变量时,会按照下面的步骤去搜索:

     

    • 函数或类的局部变量。
    • 全局变量。
    • 内置变量。

     

    以上三个步骤,其中一步骤找到对应的变量,就不会再往下找。如果在这三个步骤都找不到,就会抛出异常。

    locals与globals的区别

     

    • locals()是只读的。globals()不是。这里说的只读,是值对于原有变量的只读。其实还可以对locals()赋值的。
    • globals返回的是当前模块的全局变量 locals返回的是局部变量。注意,locals返回的是当前所在最小命名空间的局部变量的一个拷贝。
    体检locals
    [python] view plain copy
     
    1. list1 = [1,2,3]  
    2. locals()  
    3.   
    4. # 在全局中使用locals,会打印出list1和__builtins__、__name__、__doc__、__package__  
    5. 复制代码  
    6. def foo(args):  
    7.     x=1  
    8.     print locals()  
    9.   
    10. foo(123)  
    11.   
    12. #将会得到 {'arg':123,'x':1}  
    2. vars()

    本函数是实现返回对象object的属性和属性值的字典对象。如果默认不输入参数,就打印当前调用位置的属性和属性值,相当于locals()的功能。如果有参数输入,就只打印这个参数相应的属性和属性值。

    [python] view plain copy
     
    1. #vars()    
    2.     
    3. print(vars())    
    4.     
    5. class Foo:    
    6.     a = 1    
    7. print(vars(Foo))    
    8.     
    9. foo = Foo()    
    10. print(vars(foo))   
    3. eval()

    eval()函数十分强大,官方demo解释为:将字符串str当成有效的表达式来求值并返回计算结果。

    结合math当成一个计算器很好用。

    其他用法,可以把list,tuple,dict和string相互转化。见下例子:

     

    [python] view plain copy
     
    1. a = "[[1,2], [3,4], [5,6], [7,8], [9,0]]"  
    2. b = eval(a)  
    3. b  
    4. Out[3]: [[1, 2], [3, 4], [5, 6], [7, 8], [9, 0]]  
    5. type(b)  
    6. Out[4]: list  
    7. a = "{1: 'a', 2: 'b'}"  
    8. b = eval(a)  
    9. b  
    10. Out[7]: {1: 'a', 2: 'b'}  
    11. type(b)  
    12. Out[8]: dict  
    13. a = "([1,2], [3,4], [5,6], [7,8], (9,0))"  
    14. b = eval(a)  
    15. b  
    16. Out[11]: ([1, 2], [3, 4], [5, 6], [7, 8], (9, 0))  
    强大的函数有代价。安全性是其最大的缺点。

     

    想一想这种使用环境:需要用户输入一个表达式,并求值。

    如果用户恶意输入,例如:

    __import__('os').system('dir')

    那么eval()之后,你会发现,当前目录文件都会展现在用户前面。

    那么继续输入:

    open('文件名').read()

    代码都给人看了。获取完毕,一条删除命令,文件消失。哭吧!

    怎么避免安全问题?

    (1) 自行写检查函数;

    (2) 使用ast.literal_eval

    展开全文
  • Shell 变量

    千次阅读 2016-08-29 21:17:36
    同时,变量名的命名须遵循如下规则: 首个字符必须为字母(a-z,A-Z)。 中间不能有空格,可以使用下划线(_)。 不能使用标点符号。 不能使用bash里的关键字(可用help命令查看保留关键字)。 除了显式地直接赋值,...
  • 有了前面两篇的基础,下面正式开扒变量名和内存的关系,先看一段大家很熟悉的代码:  int i; scanf_s("%d", &amp;i);  int i;,在这一句就为i分配了内存(但尚未对这块内存进行初始化),所以可以...
  • 文章目录1、变量的声明1.1、标准格式1.2、简短格式1.3、批量格式2、变量的初始化2.1、标准格式2.2、编译器推导类型的格式2.3、声明并初始化3、多个变量...var 变量名 变量类型 变量声明以关键字 var 开头,后置变...
  • 成员变量、类变量(静态变量)、局部变量的区别

    千次阅读 多人点赞 2017-08-03 20:31:04
    变量名首写字母使用小写,如果由多个单词组成,从第2个单词开始的其他单词的首写字母使用大写。 如果局部变量的名字和成员变量的名字相同, 要想在该方法中使用成员变量,必须使用关键字this [java] view ...
  • C语言 常量、变量

    千次阅读 2016-01-11 09:31:52
    当我们要修改变量的数据时,系统会根据变量名找到变量对应的存储空间,将存储空间里面的数据改掉。   3> 定义 总结可得,定义变量需要2个条件:变量类型、变量名。定义变量的格式为: 变量类型 变量名; ...
  • Android配置环境变量

    千次阅读 2018-11-30 16:16:59
    1. JDK环境变量配置 我的电脑右键 ==&...变量名:JAVA_HOME 变量值:C:\Program Files\Java\jdk1.8.0_102 其中变量值:为自己安装 jdk 的路径,不知道安装在哪的点下面的链接:查看自己的SDK安装路径和JDK安...
  • weblogic安装时提示不是有效的JDK Java主目录解决方案 一.问题现象 由于项目需求,需要用weblogic作为web服务器,在开发环境安装过程中,遇到了如下的问题。 D:\Software\fmw_12.2.1.3.0_infrastructure_...
  • Volatile 变量

    千次阅读 2014-03-07 15:58:18
    Java 语言中的 volatile 变量可以被看作是一种 “程度较轻的 synchronized”;与 synchronized 块...本文介绍了几种有效使用 volatile 变量的模式,并强调了几种不适合使用 volatile 变量的情形。 锁提供了两种
  • JAVA 面向对象 成员变量和局部变量

    万次阅读 多人点赞 2016-07-20 18:08:42
    本页面更新日期: 2016年07月20日前言 在 Java语言中, 根据定义变量位置的不同,可以将变量分成两大类:成员变量 ... 下面我给出Java程序中的变量划分图: 成员变量被分为类变量和实例变量两种. 定义成员变
  • bash变量详解

    千次阅读 2016-09-03 23:26:04
    Shell作为用户和Unix/Linux沟通的桥梁,既可以是一个可执行的二进制程序,同时也是一个具备了编程能力的程序设计语言,定义了各种各样的变量和参数,下面介绍一下shell之上的各种变量(一段可变化的内存空间)。...
  • 定义变量时,变量名不加美元符号($),如:$variableName="value"如图: 注意1:1.变量名和等号之间不能有空格,这可能和你熟悉的所有编程语言都不一样。 2.变量名的命名必须遵循如下规则: * 首个字符必须为字母...
  • Volatile变量

    千次阅读 2016-05-02 20:39:11
    Java™ 语言包含两种内在的同步机制:同步块(或方法)和 volatile 变量。这两种机制的提出都是为了实现代码线程的安全性。其中 Volatile 变量的同步性较差(但有时它更简单并且开销更低),而且其使用也更容易出错...
  • Oracle-绑定变量binding variable解读

    千次阅读 2016-11-20 13:05:52
    绑定变量概述Oracle 中,对于一个提交的sql语句,存在两种可选的解析过程, 一种叫做硬解析,一种叫做软解析.一个硬解析需要经解析,制定执行路径,优化访问计划等许多的步骤.硬解释不仅仅耗费大量的cpu,更重要的是会...
  • 在不同的作用域中,同名的变量不会相互干涉,就好像 A 班有个叫小明的同学,B 班也有个叫小明的同学,虽然他们都叫小明(对应于变量名),但是由于所在的班级(对应于作用域)不同,所以不会造成混乱。但是如果同一...
  • 变量是任何一种编程语言都必不可少的组成部分,变量用来存放各种数据。脚本语言在定义变量时通常不需要指明类型,直接赋值就可以,Shell 变量也遵循这个规则。 在 Bash shell 中,每一个变量的值都是字符串,无论...
  • JavaScript中的变量提升和函数提升

    千次阅读 多人点赞 2018-03-29 14:31:26
    变量的作用域   在理解变量提升和函数提升之前,我们需要先理解好JavaScript的作用域的奇特之处。 没有块级作用域   和C、C++、以及Java不同,在ES6之前,JavaScript没有块级作用域,只有全局作用域和...
  • env 环境变量

    千次阅读 多人点赞 2019-03-19 14:23:34
    1、UNIX类系统环境变量中路径用冒号分隔,不是分号。 另外,软件越装越多,环境变量越添越多,为了避免造成混乱,建议所有语句都添加在文件结尾,按软件的安装顺序添加。 2、使用env命令显示所有的环境变量 ,...
  • Linux中shell变量说明

    千次阅读 2015-08-11 12:24:04
    shell变量可以保存诸如路径名、文件名或者一个数字这样的变量名。shell将其中任何设置都看做文本字符串。 有两种变量,本地和环境。严格地说可以有4种,但其余两种是只读的,可以认为是特殊变量,它用
  • static 变量 作用域 全局变量 局部变量 外部变量 常量 volatile变量 2人收藏此文章, 我要收藏发表于2年前 , 已有1077次阅读 共2个评论 ...作用域 全局变量 局部变量 静态变量...变量有效作用域从它的定义点
  • mysql定义变量

    千次阅读 2018-01-14 22:37:24
    1.使用set或select直接赋值,变量名以 @ 开头. 例如:set @var=1; 可以在一个会话的任何地方声明,作用域是整个会话,称为用户变量。 2.以 DECLARE 关键字声明的变量,只能在存储过程中使用,称为存储过程变量,...
  • 变量表中声明变量

    千次阅读 2019-07-27 17:26:02
    变量表中声明变量 首先我们要创建Variables表 ***Variable*** ${MgrloginUrl} http://localhost/mgr/login.html ${StudentLoginUrl} http://localhost/student/login/login.html rf变量可以在用例里面定义,也可以...
  • windows 用户变量和系统变量的区别

    千次阅读 2018-12-17 14:50:05
    点击“我的电脑→属性→高级系统设置”标签的“环境变量”按钮,出现“环境变量”对话框,如果当前是以Administrator登录系统的用户,对话框的上面为Administrator的用户变量,对话框的下面为系统变量(即相当于系统...
  • 请注意区分变量名和变量值这两个不同的概念,见图2.6。 图2.6 变量名规则 先介绍标识符的概念。和其他高级语言一样,用来标识变量、符号常量、函数、数组、类型等实体名字的有效字符序列称为标识符...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 272,885
精华内容 109,154
关键字:

下面不是有效的变量名