-
请注意区分返回函数和返回值:
def myabs(): return abs # 返回函数def myabs2(x): return abs(x) # 返回函数调用的结果,返回值是一个数值
查看全部 -
sorted()函数可对list进行排序,数字从小到大,字符串默认首字母按照ASCII大小来比较
sorted()也是一个高阶函数,它可以接收一个比较函数来实现自定义排序,比较函数的定义是,传入两个待比较的元素 x, y,如果 x 应该排在 y 的前面,返回 -1,如果 x 应该排在 y 的后面,返回 1。如果 x 和 y 相等,返回 0。
查看全部 -
看不懂的代码:
def count():
fs = []
for i in range(1, 4):
def f(j):
def g():
return j*j
return g
r = f(i)
fs.append(r)
return fs
f1, f2, f3 = count()
print f1(), f2(), f3()
查看全部 -
像这种内层函数引用了外层函数的变量(参数也算变量),然后返回内层函数的情况,称为闭包(Closure)。
闭包的特点是返回的函数还引用了外层函数的局部变量,所以,要正确使用闭包,就要确保引用的局部变量在函数返回后不能变。
查看全部 -
def calc_prod(lst):
def lazy_prod():
def f(x, y):
return x * y
return reduce(f, lst, 1)
return lazy_prod
f = calc_prod([1, 2, 3, 4])
print f()
查看全部 -
python中定义类方法
和属性类似,方法也分实例方法和类方法。
在class中定义的全部是实例方法,实例方法第一个参数 self 是实例本身。
要在class中定义类方法,需要这么写:
class Person(object): count = 0 @classmethod def how_many(cls): return cls.count def __init__(self, name): self.name = name Person.count = Person.count + 1 print Person.how_many() p1 = Person('Bob') print Person.how_many()
通过标记一个 @classmethod,该方法将绑定到 Person 类上,而非类的实例。类方法的第一个参数将传入类本身,通常将参数名命名为 cls,上面的 cls.count 实际上相当于 Person.count。
因为是在类上调用,而非实例上调用,因此类方法无法获得任何实例变量,只能获得类的引用。
查看全部 -
由于属性可以是普通的值对象,如 str,int 等,也可以是方法,还可以是函数,大家看看下面代码的运行结果,请想一想 p1.get_grade 为什么是函数而不是方法:
class Person(object): def __init__(self, name, score): self.name = name self.score = score self.get_grade = lambda: 'A' p1 = Person('Bob', 90) print p1.get_grade print p1.get_grade()
这道题答案的意思是:
练习题中的 self.get_grade 是函数没错,是函数对象,而self.get_grade() 只是函数调用,不是什么方法。
方法指的是教程中的利用 types.MethodType 得到的self.get_grade,这才是方法,加括号就是方法调用
p1.get_grade = types.MethodType(fn_get_grade, p1, Person) print p1.get_grade()
所以很明显,方法与类有关,需要传入self (参照教程前半部分),而函数不用传入self
练习题中的self.get_grade() 并没有传入self(你自己到 lambda 后面加一个 self 参数,看看程序会不会报错就知道了),它只是一个简单的函数调用
所以区分方法和函数,就看需不需要传入self (加括号只是代表调用罢了。。)
(以上均为个人观点,如有误,麻烦大佬指出)
查看全部 -
python中方法也是属性
我们在 class 中定义的实例方法其实也是属性,它实际上是一个函数对象:
class Person(object): def __init__(self, name, score): self.name = name self.score = score def get_grade(self): return 'A' p1 = Person('Bob', 90) print p1.get_grade # => <bound method Person.get_grade of <__main__.Person object at 0x109e58510>> print p1.get_grade() # => A
也就是说,p1.get_grade 返回的是一个函数对象,但这个函数是一个绑定到实例的函数,p1.get_grade() 才是方法调用。
因为方法也是一个属性,所以,它也可以动态地添加到实例上,只是需要用 types.MethodType() 把一个函数变为一个方法:
import types def fn_get_grade(self): if self.score >= 80: return 'A' if self.score >= 60: return 'B' return 'C' class Person(object): def __init__(self, name, score): self.name = name self.score = score p1 = Person('Bob', 90) p1.get_grade = types.MethodType(fn_get_grade, p1, Person) print p1.get_grade() # => A p2 = Person('Alice', 65) print p2.get_grade() # ERROR: AttributeError: 'Person' object has no attribute 'get_grade' # 因为p2实例并没有绑定get_grade
给一个实例动态添加方法并不常见,直接在class中定义要更直观。
查看全部 -
打印是因为,每次创建一个实例执行一次类里面的__init__()的print Person.__count,但是如果从外面访问Person.__count是访问不了的
查看全部 -
#创建一个函数,使它在被调用时循环变量不会被改变 def count(): #创建一个空列表,用来存储计算结果 fs = [] #使用 for...in... 循环给元素赋值,用于下面的计算 for i in range(1,4): #创建一个函数,将计算的值先存储起来 def f(X): #再创建一个函数,用于计算 f()函数内的元素,并返回结果 def g(): return x * x #将计算的结果返回函数 f(x),g 是计算结果 return g #调用 f()函数,将计算结果赋值给 a a = f(i) #再将 a 的值添加到空列表 fs 里 fs.append(a) #最后返回 fs 列表 return fs #给 range(1,4) 的三个元素对象进行赋值,然后将计算结果存储在 count() 函数,等候调用 f1,f2,f3 = count() #调用函数,打印结果 print(f1(),f2(),f3())
查看全部 -
#创建一个函数,计算一个列表的乘积,先存储起来,等到调用函数的时候再返回 def calc_prod(): def prod() #创建一个函数,结果返回 reduce()函数,计算乘积 #这里的 lambda 是一个匿名函数,后面的 x,y 是函数参数,它的值等于 x*y,然后返回 lst 进行存储 return reduce(lambda x,y: x*y,lst) #返回函数 prod(),等候调用 return prod #给 f 赋值,然后调用 calc_prod()函数 f = calc_prod([1,2,3,4)] #再次调用 f ,然后返回值 print(f)
查看全部 -
#创建一个函数,使它先计算参数内的乘积,等到调用函数的时候再返回函数本身 #创建一个函数,作用是接收一个列表 def calc_prod(lst): #创建一个函数,作用是存储一个列表 def lazy_prod(): #创建一个函数,并返回参数的乘积 def f(x,y): return x * y #先用列表存储 lst 参数的值,等调用 f()函数的时候再返回 reduce()函数,计算函数 calc_prod(lst) 里的乘积 return reduce(f,lst,1) #最后返回函数 lazy_prod,等候调用的时候再返回函数 return lazy_prod #给函数 f()的列表赋值,将值返回函数 calc_prod(lst) 的参数 lst ,暂时存储 f = calc_prod([1,2,3,4)] #调用 f()函数,计算乘积
查看全部 -
def cmp_ignore_case(s1, s2):
u1=s1.upper()
u2=s2.upper()
if u1>u2:
return 1
elif u1==u2:
return 0
else:
return -1
print sorted(['bob', 'about', 'Zoo', 'Credit'], cmp_ignore_case)
查看全部 -
python中定义实例方法
一个实例的私有属性就是以__开头的属性,无法被外部访问,那这些属性定义有什么用?
虽然私有属性无法从外部访问,但是,从类的内部是可以访问的。除了可以定义实例的属性外,还可以定义实例的方法。
实例的方法就是在类中定义的函数,它的第一个参数永远是 self,指向调用该方法的实例本身,其他参数和一个普通函数是完全一样的:
class Person(object): def __init__(self, name): self.__name = name def get_name(self): return self.__name
get_name(self) 就是一个实例方法,它的第一个参数是self。__init__(self, name)其实也可看做是一个特殊的实例方法。
调用实例方法必须在实例上调用:
p1 = Person('Bob') print p1.get_name() # self不需要显式传入 # => Bob
在实例方法内部,可以访问所有实例属性,这样,如果外部需要访问私有属性,可以通过方法调用获得,这种数据封装的形式除了能保护内部数据一致性外,还可以简化外部调用的难度。
查看全部 -
python中类属性和实例属性名字冲突怎么办
修改类属性会导致所有实例访问到的类属性全部都受影响,但是,如果在实例变量上修改类属性会发生什么问题呢?
class Person(object): address = 'Earth' def __init__(self, name): self.name = name p1 = Person('Bob') p2 = Person('Alice') print 'Person.address = ' + Person.address p1.address = 'China' print 'p1.address = ' + p1.address print 'Person.address = ' + Person.address print 'p2.address = ' + p2.address
结果如下:
Person.address = Earth p1.address = China Person.address = Earth p2.address = Earth
我们发现,在设置了 p1.address = 'China' 后,p1访问 address 确实变成了 'China',但是,Person.address和p2.address仍然是'Earch',怎么回事?
原因是 p1.address = 'China'并没有改变 Person 的 address,而是给 p1这个实例绑定了实例属性address ,对p1来说,它有一个实例属性address(值是'China'),而它所属的类Person也有一个类属性address,所以:
访问 p1.address 时,优先查找实例属性,返回'China'。
访问 p2.address 时,p2没有实例属性address,但是有类属性address,因此返回'Earth'。
可见,当实例属性和类属性重名时,实例属性优先级高,它将屏蔽掉对类属性的访问。
当我们把 p1 的 address 实例属性删除后,访问 p1.address 就又返回类属性的值 'Earth'了:
del p1.address print p1.address # => Earth
可见,千万不要在实例上修改类属性,它实际上并没有修改类属性,而是给实例绑定了一个实例属性
查看全部
举报