循序渐进Python3(六) -- 初识内置变量、反射、递归

时间:2022-12-13 13:32:03

#python用下划线作为变量前缀和后缀指定特殊变量。稍后我们会发现,  
#对于程序来说,其中的有些变量是非常有用的,而其他的则是未知或者无用的。  
#我们总结一下Python中下划线的特殊用法  
#_xxx:不用'from module import *'导入  
#__xxx__:系统定义的名字  
#__xxx:类中的私有变量名

1.__name__

#__name__指示模块应该如何被加载
#由于主程序代码无论模块是被直接执行都会运行,我们必须知道模块如何决定运行方向。
#一个应用程序可能需要导入另个引用程序的一个模块,以便重用一些有用的代码。
#这种情况下,你只想访问那些位于其它应用程序中的代码,而不是像运行那个应用程序。
#因此一个问题产生了,"Python"是否有一种方法能在运行时检测该模块是被导入还是直接被执行呢?
#__name__系统变量就是正确的答案
#如果模块是被导入,__name__的值为模块名字
#如果模块是被直接执行,__name__的值为'__main__'

if __name__ == '__main__':
    main()

以上代码表示只有在此文件执行时才会调用main()函数,其他时候则不会执行。

2.__file__

用__file__ 来获得脚本所在的路径是比较方便的,但这可能得到的是一个相对路径,比如在脚本test.py中写入:

#!/usr/bin/env python
print __file__

按相对路径./test.py来执行,则打印得到的是相对路径,
按绝对路径执行则得到的是绝对路径。
而按用户目录来执行(~/practice/test.py),则得到的也是绝对路径(~被展开)

所以为了得到绝对路径,我们需要 os.path.realpath(__file__)。

3.__doc__

文档字符串。一般而言,是对函数/方法/模块所实现功能的简单描述。但当指向具体对象时,会显示此对象从属的类型的构造函数的文档字符串。


'''
本文件__doc__输出
'''
if __name__=='__main__':
print(__doc__) # print globals()['__doc__']
Login_User = {"is_login":False} def check_login(func):
"""
此处为函数__doc__变量输出值
:param func:
:return:
"""
def chk_inner(*args,**kwargs):
if Login_User["is_login"]:
func()
else:
print('请登录')
return chk_inner
print(check_login.__doc__) # 输出结果
本文件__doc__输出 此处为函数__doc__变量输出值
:param func:
:return:

4.__package__  和 __name__ 类似,当自己调用的时候返回none,当通过导入操作后输出文件所在的目录名

import os,sys
from lib import class6
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
sys.path.append(BASE_DIR)
print(__package__)
print(class6.__package__) # 输出
None
lib

hasattr(object, name)

说明:判断对象object是否包含名为name的特性(hasattr是通过调用getattr(ojbect, name)是否抛出异常来实现的)。

参数object:对象。

参数name:特性名称。

示例:

>>> hasattr(list, 'append')
True >>> hasattr(list, 'add')
False
getattr()
getattr()函数是Python自省的核心函数,具体使用大体如下:

获取对象引用getattr
Getattr用于返回一个对象属性,或者方法


    1. class A:
    2. def __init__(self):
    3. self.name = 'zhangjing'
    4.     #self.age='24'
    5. def method(self):
    6. print"method print"
    7. Instance = A()
    8. print getattr(Instance , 'name, 'not find') #如果Instance 对象中有属性name则打印self.name的值,否则打印'not find'
    9. print getattr(Instance , 'age', 'not find')   #如果Instance 对象中有属性age则打印self.age的值,否则打印'not find'
    10. print getattr(a, 'method', 'default')
    11. #如果有方法method,否则打印其地址,否则打印default
    12. print getattr(a, 'method', 'default')()
    13. #如果有方法method,运行函数并打印None否则打印default
 

sys.modules

与其它任何 Python 的东西一样,模块也是对象。只要导入了,总可以用全局 dictionary sys.modules 来得到一个模块的引用。
 是一个字典,它包含了从 Python 开始运行起,被导入的所有模块。键字就是模块名,键值就是模块对象。请注意除了你的程序
导入的模块外还有其它模块。Python 在启动时预先装入了一些模块,如果你在一个 Python IDE 环境下,sys.modules 包含了你
在 IDE 中运行的所有程序所导入的所有模块。 反射

反射的作用就是列出对象的所有属性和方法,反射就是告诉我们,这个对象到底是什么,提供了什么功能 。

举个例子:

>>> import json
>>> dir(json)             
['JSONDecoder', 'JSONEncoder', '__all__', '__author__', '__builtins__', '__doc__', '__file__', '__name__', '__package__', '__path__', '__version__', '_default_decoder', '_default_encoder', 'decoder', 'dump', 'dumps', 'encoder', 'load', 'loads', 'scanner']
>>>

如上所看,dir 是一个内置的 反射函数 ,可以列出对象的属性和方法。

再看另外一个内置的方法 :getattr

>>> getattr(json,'encoder')
<module 'json.encoder' from '/usr/lib/python2.7/json/encoder.pyc'>
>>> getattr(json,'load')
<function load at 0x7f66af736140>
>>>

可以取出指定属性

再看另外一个方法 :callable

>>> callable(getattr(json,'load'))
True
>>> callable(getattr(json,'encoder'))
False
>>>

检查属性是否是可以调用的函数 。

了解基础之后,就需要考虑,它存在的价值在哪里了?

考虑一个应用的场景:IDE的自动补全。

在IDE中可以这样做:

>>> methodList = [attr for attr in dir(json)  if callable(getattr(json,attr))]
>>> methodList
['JSONDecoder', 'JSONEncoder', 'dump', 'dumps', 'load', 'loads']
>>>

>>> getattr(json,'load').__doc__
'Deserialize ``fp`` (a ``.read()``-supporting file-like object containing\n    a JSON document) to a Python object.\n\n    If the contents of ``fp`` is encoded with an ASCII based encoding other\n    than utf-8 (e.g. latin-1), then an appropriate ``encoding`` name must\n    be specified. Encodings that are not ASCII based (such as UCS-2) are\n    not allowed, and should be wrapped with\n    ``codecs.getreader(fp)(encoding)``, or simply decoded to a ``unicode``\n    object and passed to ``loads()``\n\n    ``object_hook`` is an optional function that will be called with the\n    result of any object literal decode (a ``dict``). The return value of\n    ``object_hook`` will be used instead of the ``dict``. This feature\n    can be used to implement custom decoders (e.g. JSON-RPC class hinting).\n\n    ``object_pairs_hook`` is an optional function that will be called with the\n    result of any object literal decoded with an ordered list of pairs.  The\n    return value of ``object_pairs_hook`` will be used instead of the ``dict``.\n    This feature can be used to implement custom decoders that rely on the\n    order that the key and value pairs are decoded (for example,\n    collections.OrderedDict will remember the order of insertion). If\n    ``object_hook`` is also defined, the ``object_pairs_hook`` takes priority.\n\n    To use a custom ``JSONDecoder`` subclass, specify it with the ``cls``\n    kwarg; otherwise ``JSONDecoder`` is used.\n\n    '
>>>

大概就明白了 反射的功能了。

#-*- coding:utf8 -*-

class Obj :
    """ An object that use reflection """

def __init__(self,name):
        """ 构造函数 """
        self.name = name

def echo_methods(self):
        """ 输出类中所有的方法,以及doc 文档 """
        print "\n Method List: "
        for attrName in dir(self):
            attr = getattr(self,attrName)
            if callable(attr):
                print attrName,"():",attr.__doc__

def echo_attributes(self):
        print "\n Attributes"

for name in dit(self):
            attr = getattr(self,attr)
            if not callable(attr):
                print name,":",attr

obj = Obj("testObject")
obj.echo_methods()

ubuntu@yee:/tmp$ python ref.py

Method List:
__init__ ():  构造函数
echo_attributes (): None
echo_methods ():  输出类中所有的方法,以及doc 文档

可以看到,通过反射,我们可以知道类中所有的方法以及方法的属性和注释文档信息。

内置函数__import__

我们知道import语句是用来导入外部模块的,当然还有from...import...也可以,但是其实import实际上是使用builtin函数__import__来工作的。
    在一些程序中,我们可以动态地去调用函数,如果我们知道模块的名称(字符串)的时候,我们可以很方便的使用动态调用。

  1. import glob,os
  2. modules = []
  3. for module_file in glob.glob("*-plugin.py"):
  4. try:
  5. module_name,ext = os.path.splitext(os.path.basename(module_file))
  6. module = __import__(module_name)
  7. modules.append(module)
  8. except ImportError:
  9. pass #ignore broken modules
  10. #say hello to all modules
  11. for module in modules:
  12. module.hello()
 导入其他目下的模块:
   使用参数  fromlist=True,进行字符串拼接。
 

递归

递归(recursion):程序调用自身的编程技巧。
  递归满足2个条件:
    1)有反复执行的过程(调用自身)
    2)有跳出反复执行过程的条件(递归出口)

(1)阶乘
         n! = n * (n-1) * (n-2) * ...* 1(n>0)

def recursion(x):
if x == 1:
y = 1
else:
y = x * recursion(x - 1)
return y print(recursion(5))

(2)斐波那契数列

斐波纳契数列,又称黄金分割数列,指的是这样一个数列:1、1、2、3、5、8、13、21、……

这个数列从第三项开始,每一项都等于前两项之和。

有趣的兔子问题:

循序渐进Python3(六) -- 初识内置变量、反射、递归

一般而言,兔子在出生两个月后,就有繁殖能力,一对兔子每个月能生出一对小兔子来。如果所有兔子都不死,那么一年以后可以繁殖多少对兔子?

分析如下:

第一个月小兔子没有繁殖能力,所以还是一对;

两个月后,生下一对小兔子,总数共有两对;

三个月以后,老兔子又生下一对,因为小兔子还没有繁殖能力,总数共是三对;

…… 

依次类推可以列出下表:

循序渐进Python3(六) -- 初识内置变量、反射、递归

def fibo(n):
if n == 0:
return 0
if n == 1:
return 1
if n > 1:
return fibo(n - 1) + fibo(n - 2) print(fibo(4))
 
 
 
 

循序渐进Python3(六) -- 初识内置变量、反射、递归的更多相关文章

  1. Makefile内置变量,递归式变量,直接展开式变量,条件赋值,追加赋值

    将shell命令的输出赋值给变量: VALUE = $(shell   命令) Makefile中给变量赋值: =     是递归展开式变量 value1 = 5 value2 = $(value1) ...

  2. Python每日一练------内置函数&plus;内置变量&plus;内置模块

    1.内置函数 Python所有的内置函数     Built-in Functions     abs() divmod() input() open() staticmethod() all() e ...

  3. python3&period;7&period;1 内置函数

    python3.7.1 内置函数列表 内置函数 abs() delattr() hash() memoryview() set() all() dict() help() min() setattr( ...

  4. Maven系列三Maven内置变量

    Maven内置变量说明: ${basedir} 项目根目录(即pom.xml文件所在目录) ${project.build.directory} 构建目录,缺省为target目录 ${project. ...

  5. Maven的内置变量

    Maven内置变量说明: ${basedir} 项目根目录(即pom.xml文件所在目录) ${project.build.directory} 构建目录,缺省为target目录 ${project. ...

  6. nginx的那些内置变量

    nginx在配置文件nginx.conf中可以使用很多内置变量,配置如下: location /info { add_header 'Content-Type' 'text/html'; echo & ...

  7. Maven内置变量说明

    Maven内置变量说明: ${basedir} 项目根目录 ${project.build.directory} 构建目录,缺省为target ${project.build.outputDirect ...

  8. 学习笔记——Maven 内置变量

    Maven内置变量说明: ${basedir} 项目根目录(即pom.xml文件所在目录) ${project.build.directory} 构建目录,缺省为target目录 ${project. ...

  9. makefile 分析 -- 内置变量及自动变量

    makefile 分析1  -p 选项,可以打印出make过程中的数据库, 下面研究一下内置的变量和规则. -n 选项, 只运行,不执行, -d 选项,相当于--debug=a,  b(basic), ...

随机推荐

  1. Eclipse添加JPDL4 Schema校验

    由于jbpm官方提供的图形化流程设计器(GPD)功能并不是特别的全面,很多设计并不能全在图形界面下完成.因此,在很多情况下,我们需要直接编辑JPDL的XML源代码,所以, 最好为JPDL XML指定S ...

  2. awk&lpar;1&rpar;-简述

    1.概述 AWK is a programming language designed for text processing and typically used as a data extract ...

  3. iOS学习系列-Apache服务器的配置

    配置Apache服务器 一.目的 能够有一个测试的服务器,不是所有的特殊网络服务都能找到免费得! 二.为什么我们要用"Apache"? Apache是目前使用最广的web服务器 M ...

  4. Android系统架构

    Linux内核层 为Android的各种设备提供了底层驱动 系统运行库层 为Android提供一些底层的库,如数据库.3D绘图等 应用框架层 核心API 应用层 具体的手机application An ...

  5. C语言 串 顺序结构 实现

    一个能够自动扩容的顺序结构的串 ArrString (GCC编译). /** * @brief C语言 串 顺序结构 实现 * @author wid * @date 2013-11-01 * * @ ...

  6. Ubuntu格式化分区时的一个小错误

    admin@gpc:/$ sudo  mkfs -t ext3 -c /dev/sdb1 mkfs.ext3: inode_size (128) * inodes_count (0) too big ...

  7. &sol;proc&sol;mtd 各参数的含义 -- linux内核

    经/proc虚拟文件系统读取MTD分区表:cat /proc/mtd mtd .name = raspi, .size = 0x00400000 (4M) .erasesize = 0x0001000 ...

  8. DBCP 连接池

    DBCP数据源 DBCP 是 Apache 软件基金组织下的开源连接池实现 导入maven包: <!-- dbcp连接池 --> <dependency> <groupI ...

  9. java框架之SpringBoot&lpar;15&rpar;-安全及整合SpringSecurity

    SpringSecurity介绍 Spring Security 是针对 Spring 项目的安全框架,也是 Spring Boot 底层安全模块默认的技术选型.它可以实现强大的 Web 安全控制.对 ...

  10. iOS 几种加密方法

    iOS常见的几种加密方法 普通加密方法是讲密码进行加密后保存到用户偏好设置中 钥匙串是以明文形式保存,但是不知道存放的具体位置 1.base64加密 base64 编码是现代密码学的基础 基本原理: ...