1.类的私有属性以__开头,无法通过外部访问,只能通过内部方法访问,为了保护类或实例属性不被外部污染而设计的。
4-4 Python类的数学运算
如何理解def __add__(self, r):
return Rational(self.p * r.q + self.q * r.p, self.q * r.q)
>>> r1 = Rational(1, 2)
>>> r2 = Rational(2, 3)
>>> print(r1 + r2)
思路过程:
不理解r是什么,后面经过查找,代码存在r1+r2时才会调用__add__()函数,此时self.p和self.q指的是r1的p和q,而r.p和r.q指的是r2.p和r2.q
也就是 (1*3+2*2)/2*3 有理数的答案
class Rational(object): def __init__(self, p, q): self.p = p self.q = q def __add__(self, r): return Rational(self.p * r.q + self.q * r.p, self.q * r.q) def __str__(self): return '{}/{}'.format(self.p, self.q) r1 = Rational(1, 2) r2 = Rational(2, 3) r3 = Rational(1, 6) print(r1+r2) print(r1.__add__(r2))
重载运算符:
r1+r2 和
r1.__add__(r2) 相同
class Fib(object): def __init__(self,num): self.num=num def __len__(self): return len(self.num) f = [0,1,1,2,3,5,8,13,21,34] f_ = Fib(f) print(f) print(len(Fib(f)))
Fib是一个类
f_ 是这个类的一个实例,等同于Fib(f)
f 是一个列表,也是f_ 的属性
私有属性从类的内部进行访问
第5行
class Animal(object): def __init__(self,name,age): self.name=name self.__age=age print(self.__age) dog=Animal('D',5)
1,实例属性的优先级高于类属性
2,通过实例可以访问类属性,但不能修改类属性
3,类属性私有化之后,不能从外部访问,只能在类内部访问
在Python中初次操作文件可能会尝试先读file.white()后写file.read(),结果会发现明明已经写入数据,但读出内容依然为空的问题。
如下例:
file = open('./a.txt', mode="a+", encoding="utf8")
file.write("123456")
str = file.read()
print(str)
# 读出内容为空
# a.txt 内容为123456
1
2
3
4
5
6
造成这种问题的原因是,当写入操作完成时,文件光标处于文件末尾处;接着继续执行读取操作,系统从光标处向后读取,但光标已处于末尾,所以读出内容为空。
该问题有两种解决方案:
方法一:规范代码,将读取操作与写入操作分类,在一种操作执行结束后应及时关闭文件指针file.close()。使用这种方法可以是文件安全有效,不会被其他操作影响预计效果。
如下:
# 写入
file = open('./a.txt', mode="w", encoding="utf8")
file.write("123456")
file.close()
# 读取
file = open('./a.txt', mode="r", encoding="utf8")
str = file.read()
print(str)
# 输出为 123456
# a.txt 123456
1
2
3
4
5
6
7
8
9
10
方法二:使用seek()方法移动光标至指定位置
file.seek(offset,whence=0)
offset:偏移量,即需要移动偏移的字节数。
whence:要从哪个位置开始偏移,默认值为0;0代表从文件开头开始算起,1代表从当前位置开始算起,2代表从文件末尾算起。
同时whence也可以使用常量名表示(需要引入os模块):
whence常量:
os.SEEK_SET: 0 相对文件起始位置
os.SEEK_CUR: 1 相对文件的当前位置
os.SEEK_END: 2 相对文件的结束位置
对于本问题,可以在写入之后将光标从新移动至文件开头位置,然后执行读取操作
file = open('./a.txt', mode="a+", encoding="utf8")
file.write("123456")
# 表示移动0个位置,从文件开头开始
file.seek(0, 0)
str = file.read()
print(str)
# 输出为 123456
# a.txt 123456
1
2
3
4
5
6
7
8
注意:Python3中不支持非二进制的文件光标移动位置且offset按位取值,所以非二进制文件建议只使用将光标移动到开头或末尾的功能,即offset==0,避免出现io.UnsupportedOperation: can't do nonzero cur-relative seeks或者io.UnsupportedOperation: can't do nonzero end-relative seeks的错误
————————————————
版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
原文链接:https://blog.csdn.net/w18211679321/article/details/81451838
# Enter a
def say_hello(name):
print('您好呀,{}'.format(name))
print(f"你好啊,{name}")
print("宁浩呀,我是%s"%name)
say_hello("xioaming")
class Person(object):
def __init__(self, name, gender):
self.name = name
self.gender = gender
class Student(Person):
def __init__(self, name, gender, score):
super(Student, self).__init__(name, gender)
self.score = score
def __str__(self):
return 'Student: {}, {}, {}'.format(self.name, self.gender, self.score)
def __repr__(self):
return 'STUDENT: {}, {}, {}'.format(self.name, self.gender, self.score)
s = Student('Bob', 'Male', 88)
print(s)
print('%s' % s)
print('%r' % s)
print(str(s))
print(repr(s))
Teacher 继承 Student 时,__init__()括号中需要写被继承类的全部参数, super(Teacher, self).__init__(name, gender)报错是因为缺少了Student的score参数; t = Teacher('Alice', 'Female', 'English') Teacher继承Student的三个参数后又定义了course参数,共4个参数,这个地方少了一个参数
有参数的decorator
在外面套一层专门接收参数的函数
例:
请给 @performace 增加一个参数,允许传入's'
import time from functools import reduce def performance(prefix): def performance_decorator(f): def fn(*args, **kwargs): t1 = time.time() f(*args, **kwargs) t2 = time.time() print('函数f运行时间是{}{}'.format(t2 - t1,prefix)) return fn return performance_decorator @performance('s') def f(list_): return reduce(lambda x,y: x*y, list_) f(list(range(1,10000)))
解释:
def performance(参数):
def performance_decorator(函数f):
...
return performance_decorator
performance_decorator = performance(参数)
新函数 = performance_decorator(原函数)
装饰器的作用:
给原函数装饰装饰变成新函数
装饰器的语法:
@+装饰器函数名
例:
编写一个decorator计算函数的运行时间
import time from functools import reduce def performance(f): def fn(*args, **kwargs): t1 = time.time() f(*args, **kwargs) #接收函数用*args,**kwargs;在函数中用args,kwargs t2 = time.time() print('函数f运行时间是{}s'.format(t2 - t1)) return fn @performance def f(list_): return reduce(lambda x,y: x*y, list_) f(list(range(1,100000))) ==>函数f运行时间是2.1856231689453125s
解释:
将函数f作为参数传给函数performance
函数performance接收原函数f
在函数performance中定义新函数fn,新函数的参数用来接收原函数的参数,一般设为*args,**kwargs可接收任何形式参数
装饰原函数
返回新函数fn
def calc_sum(list_): def lazy_sum(): return sum(list_) return lazy_sum f = calc_sum([1, 2, 3, 4]) f() ==>10
闭包:
内层函数引用外层函数的变量(参数也算是变量),最后外层函数返回内层函数
那么这个内层函数就是一个闭包(类似打包返回)
错误写法:
# 希望一次返回3个函数,分别计算1x1,2x2,3x3: def count(): fs = [] for i in range(1, 4): def f(): return i*i fs.append(f) return fs f1, f2, f3 = count() #内层函数只被定义还没运行,此时外层函数运行完毕i=3 f1()==>9 #运行内层函数 f2()==>9 f3()==>9
正确写法:
def count(): fs=[] for i in range(1,4): def g(j=i): #为内层函数设置形参默认值 return j*j fs.append(g) return fs f1,f2,f3=count() print(f1(),f2(),f3())
在Python中,函数形参默认值是指在定义函数时为形参指定的默认值,在调用函数时,如果没有为该形参提供实际的参数值,函数会使用默认值
Python在函数内部定义子函数,并把子函数返回
def f(): def g(): return ... return g x = f() x()
函数名g就是指向函数g的变量
不加小括号就只是一个变量,加上小括号才能调用函数
匿名函数
lambda 参数 : 表达式
可以有多个参数,但只能有一个表达式,返回值就是表达式的结果
例:
map(lambda x:x*x,[1,2,3,4]) reduce(lambda x,y:x*y,[1,2,3,4]) sorted(['bob', 'about', 'Zoo', 'Credit'],key=lambda x:x.lower())
sorted(list, (key=函数对象f, reverse=True)) 默认从小到大排序
函数f的作用:
接受待排序列表的元素作为参数传入函数f,并返回真正需要排序的字段
例1:
(姓名,成绩)按成绩进行排序
def f(item): return item[1] print(sorted([('Alice', 72), ('Candy', 90), ('Bob', 62)],key=f)) ==>[('Bob', 62), ('Alice', 72), ('Candy', 90)]
例2:
对字符串忽略大小写进行排序
def f(item): return item.lower() print(sorted(['bob', 'about', 'Zoo', 'Credit'],key=f)) ==>['about', 'bob', 'Credit', 'Zoo']