1.回归函数
上述是廖雪峰教程中的代码。
先分析一下代码:
一个count()返回一个list,list里面的元素是3个函数。由于参数J是根据循环i(可变参数)而定,而参数的分配往往是等返回全部函数才返回参数。因此只会得到9,9,9.而上面增加了多一个def f(j)用于在每次循环都实时返回参数,所以才得到1,4,9
之前一直困惑,能不能不要def g()和return g,直接用def f(j),然后内容就直接return j×j。这样也实时返回了i。
显然是不行的,而且def f(j)这个多一层的返回函数是不能忽略。有上面的困惑最主要是我忽略了在return 中 return f 和return f()的差别。return f是返回函数,而return f()是直接执行函数。
也就是说执行count()后,是这样的list【g(j),g(j),g(j)】而不是我想的【f(j),f(j),f(j)】,因此要么fs.append()括号中填f而不是f(),要么就像上面增加一个返回函数f。还有网有的大神方法,如下
2.装饰器
廖雪峰装饰器作业:
答案:
import functools
def log(pointer): #pointer是个变量,在这里能指向函数或者str,这就要看if条件
if not isinstance(pointer,str): #如果pointer不是字符串,pointer指向函数func,
@functools.wraps(pointer)
def wrapper(*args,**kw):
print 'begin %s,test:none' % pointer.__name__
return pointer(*args,**kw)
return wrapper
else:#不然的话,pointer指向str
def decorator(func):
@functools.wraps(func)
def wrapper(*args,**kw):
print 'begin %s,test:%s' % (func.__name__,pointer)
return func(*args,**kw)
return wrapper
return decorator
3.元类metaclass
对象-关系映射表
#!/usr/bin/env python
# -*- coding: utf-8 -*-
#对象-关系映射表 ,先声明一下: u=user(~)
class Field(object):
def __init__(self, name,column_type): #字段名,字段类型
self.name = name
self.column_type = column_type
def __str__(self):
#如果直接print Field,返回类的名字(这里是Field)和字段名
return '%s:%s' %(self.__class__.__name__,self.name)
#用于定义
class StringField(Field):
def __init__(self,name): #super让本子类继承了两属性,name和column_type
super(StringField,self).__init__(name,'varchar(100)')
class IntegerField(Field):
def __init__(self,name):
super(IntegerField,self).__init__(name,'varchar(100)')
class ModelMetaclass(type): #创建类都需要从type中派生
#cls是元类对象ModelMetaclass,name是类名,bases是类继承的父类集合(dict),
# attrs是类的方法集合(就是ID,email那个,82行附近,暂时不了解为啥会等于attrs)
def __new__(cls,name,bases,attrs):
#如果类名是'Model',就直接返回一个类
if name == 'Model': #在本例中,先由name为model创立model类,然后再由名为user创立一个user类,看46行
return type.__new__(cls,name,bases,attrs)
#创建一个dict
mappings = dict()
#抽取attrs中的集合
for k,v in attrs.iteritems():
#判断获取的value是否是Field类型,(Value通常是Field的子类)
if isinstance(v,Field):
# 打印指向实例的变量,实例信息
print ('Found mapping: %s==%s' %(k,v))
#如果value是FIeld类型,将该key和value放进mappings的dict中
mappings[k] = v
for k in mappings.iterkeys():
#删除attrs里面被放进mappings中相同的key,对应的value也会被删除
attrs.pop(k)
attrs['__table__'] = name
#python允许在dict中放入一个dict
attrs['__mappings__'] = mappings
return type.__new__(cls,name,bases,attrs)
class Model(dict):
#以ModelMetaclass的__new__来创建MOdel这个类
__metaclass__ = ModelMetaclass
def __init__(self,**kw): #self是一个dict,由于user继承model,model继承dict,所以在生成实例时user(参数)括号里参数是传入类似与**kw的参数,参数会自动转化成dict.
super(Model,self).__init__(**kw)
def __getattr__(self,key):
#比如尝试返回u[age],没有则报错
try:
return self[key]
except KeyError:
raise AttributeError(r"'Model' object has no attribute '%s'" % key)
#允许u[key] = value 赋值
def __setattr__(self,key,value):
self[key] =value
def save(self):
fields = []
params = []
args = []
for k,v in self.__mappings__.iteritems(): #__mappings__存储的是84行dict
fields.append(v.name) #v.name是各实例中name属性的值
params.append('?')
args.append(getattr(self,k,None)) #k是指向实例的变量名,根据__getattr__函数返回的是
sql = 'insert into %s (%s) values (%s)' %(self.__table__,','.join(fields),','.join(params))
print('SQL:%s' % sql)
print('ARGS:%s' % str(args))
class User(Model):
# 定义类的属性到列的映射:
# 创造了类似于这样一个dict
# {ID:<__main.StringField object at 0x017AD830>,name:(基于StringField的实例),email:(~实例),password:(~实例)}
# 这个dict就是等等在__new__中代入的attrs
id = IntegerField('uid')
name = StringField('username')
email = StringField('email')
password = StringField('password')
# 创建一个实例:
u = User(id=12345, name='Michael', email='test@orm.org', password='my-pwd')
# 保存到数据库:
u.save()
#输出结果如下
# Found model: User
# Found mapping: email ==> <StringField:email>
# Found mapping: password ==> <StringField:password>
# Found mapping: ID ==> <IntegerField:uid>
# Found mapping: name ==> <StringField:username>
# SQL: insert into User (password,email,username,uid) values (?,?,?,?)
# ARGS: ['my-pwd', 'test@orm.org', 'Michael', 12345]
上述代码大概思路是:
①在创建user类时,就包含了在user下的所有属性(但不包括括号里面的,比如id = 12345),就是那个id=IntegerField('uid')那4个。
②由于user类继承了model类,而model中又有__metaclass__=modemetaclass类,所以会先用modemetaclass类中的__new__()方法创建model函数,然后user在通过modemetaclass中的__new__()方法创建user函数,同时继承拥有model所有的方法和属性.
③在modemetaclass类中的__new__的大概意思是:attrs是一个字典,里面包含了4个key和value,也就是id=IntegerField('uid')那4个,id是key,=号后面的是value.判断字典中的所有值value是否继承Field类,满足的话,将那个value和对应的key都放进__mappings__这个字典中(__mappings__是新创建的dict).然后将__mappings__字典保存在attrs字典中(也即是字典中的字典),并创建一个新key(__table__)表名和值放在attrs中,同时清空attrs中有的,但__mappings中也有的相同key和值,清的是attrs中的.这是attrs只有两个key,也就是__mappings__和__table__
④上面都是创造类的,就是不会运行如下面括号中的内容,比如(id=12345,,,,)
# 创建一个实例:
u = User(id=12345, name='Michael', email='test@orm.org', password='my-pwd')
现在创建实例,就要用到括号中的参数.
虽然在创建实例和创建类时,都用了相同的属性,比如id,创建类是指向一个实例IntegerField('uid')用于判断其是否继承Field类,创建实例是id是指向一个整型12345.
由于继承dict类,所以创造实例后,变量u指向的实例实际上是一个字典.该字典就是{'id':12345,'name':'Michael'....}那4个.
4.搜索所以子目录包含有‘t’的文件
import os
def search(s,dir=os.path.abspath('.')):
for x in os.listdir(dir): #通过循环列出当前目录的文件及文件夹列表
newpath=os.path.join(dir,x) #对列表中的文件及文件夹都添加路径
if os.path.isfile(newpath) and (s in os.path.splitext(x)[0]): #判断是否是文件并且文件名中是否包含test字符
print newpath #打印路径
if os.path.isdir(newpath): #判断是否文件夹
search(s,newpath) #递归search,第二级search和第一级search中的属性互补影响
if __name__ == '__main__':
search('test')