python100day学习第二周
# 通过enumerate函数处理列表之后再遍历可以同时获得元素索引和值 list1 = [1, 3, 5, 7, 100] for index, elem in enumerate(list1): print(index, elem)
文件后缀名
#返回一个文件的后缀名 def getSuffix(filename): suffix = filename.rfind('.') return filename[suffix+1:] print(getSuffix("hello.txt"))
返回列表中最大和第二大的值
# 返回列表中最大和第二大的值 def max12(listname): max1 = max(listname) newlist = listname.remove(max1) max2 = max(listname) return max1,max2 result = max12([1,2,3,5,4]) print(result)
约瑟夫问题
# 约瑟夫环问题 # 30个数,开始循环,如果到9,则标记为0 def yuesefu(): persons = [1]*30 total_sum = 0 loc = 0 num = 0 while total_sum < 15: if persons[loc]: num += 1 if num == 9: total_sum += 1 persons[loc] = 0 num = 0 loc += 1 loc %= 30 return persons print(yuesefu())
python的==和is有区别,is比较两个对象的id,==比较值是否相等
def main(): x = y = -1 while True: x += 1 y += 1 if x is y: print('%d is %d' % (x, y)) else: print('Attention! %d is not %d' % (x, y)) break x = y = 0 while True: x -= 1 y -= 1 if x is y: print('%d is %d' % (x, y)) else: print('Attention! %d is not %d' % (x, y)) break if __name__ == '__main__': main()
Python把一些频繁使用的整数对象缓存起来,保存到一个叫small_ints的链表中,在Python的整个生命周期内,任何需要引用这些整数对象的地方,都不再重新创建新的对象,而是直接引用缓存中的对象。Python把频繁使用的整数对象的值定在[-5, 256]这个区间,如果需要这个范围的整数,就直接从small_ints中获取引用而不是临时创建新的对象。因为大于256或小于-5的整数不在该范围之内,所以就算两个整数的值是一样,但它们是不同的对象
但是如果在同一模块中,那么是地址相同
a = 257 def main(): b = 257 # 第6行 c = 257 # 第7行 print(b is c) # True print(a is b) # False print(a is c) # False if __name__ == "__main__": main()
python的下划线小结
python的单下划线
如果是交互式情况下,单下划线表示上一条语句的输出结果
>>> "python" 'python' >>> _ 'python' >>>
作为临时变量,在for循环中充当i
for _ in range(5): print(_)
名称前加单下划线表示私有(末尾加双下划线没什么影响),不强制,仅作为提示
# 前置单下划线对于类调用影响不大 # 但是如果是导包,则需在__all__中声明才可以调用 class Student(): def __init__(self,name,age): self._name = name self.age = age stu1 = Student("lp",18) print(stu1._name) print(stu1.age)
双下划线
前置双下划线
# 前置双下滑线才算比较好的设置保护 # 这时候需要._类名__属性名才能进行调用 class Student(): def __init__(self,name,age): self.__name = name self.age = age stu1 = Student("lp",18) print(stu1._Student__name) print(stu1.age)
首尾双下划线(好像没见到过尾部双下划线的)
一般是作为固定搭配__init__之类的
continue和pass的区别
a = 'python' i = 2 for element in a: if element == 'y': pass i = 3 else: print(element+str(i)) """ p2 t3 h3 o3 n3 """
a = 'python' i = 2 for element in a: if element == 'y': continue i = 3 else: print(element+str(i)) """ p2 t2 h2 o2 n2 """
在打开的文件中,首先最好使用with open("xxx.xx") as xxxx:这样的形式
然后对于read()和readline(),产生的是str,如果是readlines,则产生的是list
这里在同目录下创建test.txt,里面的内容为
# test.txt 1212121 21131241422141 2144121331 2131313123123
这里分别用不同的方法查看输出
with open("./test.txt") as fobj: print(fobj) print(type(fobj)) for line in fobj: print(line)
with open("./test.txt") as fobj: contents = fobj.read() print("contents:",contents) print("**********************") print("type(contents):",type(contents)) print("**********************") for line in fobj: print(line)
这里你可能会奇怪我为什么这样输出,这是因为下面的print(line)不输出了
with open("./test.txt") as fobj: contents = fobj.read() print("contents:",contents) print("type(contents):",type(contents))
with open("./test.txt") as fobj: contents = fobj.readlines() print("contents:",contents) print("type(contents):",type(contents)) for line in contents: print(line)
继续回到前置单下划线,如果此时想设置成私有的,那么可以使用getter和setter方法
getter和setter方法
class Person(object): def __init__(self, name, age): self._name = name self._age = age # 访问器 - getter方法 @property def name(self): return self._name # 访问器 - getter方法 @property def age(self): return self._age # 修改器 - setter方法 @age.setter def age(self, age): self._age = age def play(self): if self._age <= 16: print('%s正在玩飞行棋.' % self._name) else: print('%s正在玩斗地主.' % self._name) def main(): person = Person('王大锤', 12) person.play() person.age = 22 person.play() # person.name = '白元芳' # AttributeError: can't set attribute if __name__ == '__main__': main()
其实觉得这个getter和setter方法还是没什么用,因为还是可以用._的方法来调用
但是后面自己再去实现了一下前置双下划线,发现还是很有用的
class Person(): def __init__(self,name,age): self.__name = name self.__age = age @property def name(self): return self.__name person = Person("xxx",18) person.name
请注意,下面我刻意把name打成了nam,调用的时候也必须使用.nam
class Person(): def __init__(self,name,age): self.__name = name self.__age = age @property def nam(self): return self.__name @nam.setter def nam(self,nam): self.__name = nam person = Person("xxx",18) person.nam
@property装饰器的作用:既要保护类的封装特性,又要让开发者可以使用“对象.属性”的方式操作操作类属性
注意
,不加@property不会变成getter方法,输出只会是类中的一个方法
可以查看下面两种输出
使用return方法:
class Person(): def __init__(self,name,age): self.__name = name self.age = age def name(self): return self.__name def age(self): return self.age person = Person("xxx",18) print(person.name) print(person.age) <bound method Person.name of <__main__.Person object at 0x000001B47B0E61F0>> 18
使用print方法
class Person(): def __init__(self,name,age): self.__name = name self.age = age def name(self): print(self.__name) def age(self): print(self.age) person = Person("xxx",18) print(person.name) print(type(person.name)) print(person.age) print(type(person.age)) # 这里age会自动识别成属性,而不是方法 person.age("hello") person.age()
在上面的例子中,我们知道如果属性和方法重名,会自动识别为属性,不会像Java一样,当然我们一般也不会这样做,再看下面这两个例子会更清楚地理解为什么会有@property地getter方法,以及@修饰属性.setter方法,@property装饰器会将方法转换为相同名称的只读属性,可以与所定义的属性配合使用,这样可以防止属性被修改。
class Student(): def __init__(self,name,age): self.name = name self.age = age def name(self): print(self.name+"hello") stu = Student("xxx",18) print(stu.name) stu.name()
class Student(): def __init__(self,name,age): self.__name = name self.age = age def name(self): print(self.name+"hello") stu = Student("xxx",18) print(stu.name)
学到这里,那同样把property函数也学习了一下
property(fget=None, fset=None, fdel=None, doc=None) -> property attribute
直接看例子
class Student: def __init__(self): self._age = None def get_age(self): print('获取属性时执行的代码') return self._age def set_age(self, age): print('设置属性时执行的代码') self._age = age def del_age(self): print('删除属性时执行的代码') del self._age age = property(get_age, set_age, del_age, '学生年龄') student = Student() # 注意要用 类名.属性.__doc__ 的形式查看属性的文档字符串 print('查看属性的文档字符串:' + Student.age.__doc__) """ 查看属性的文档字符串:学生年龄 """ # 设置属性 student.age = 18 """ 设置属性时执行的代码 """ # 获取属性 print('学生年龄为:' + str(student.age)) """ 获取属性时执行的代码 学生年龄为:18 """ # 删除属性 del student.age """ 删除属性时执行的代码 """
上例中,可一步一步调试,最后del student.age
,再查看student.age
静态方法暂时还是没感觉有什么用,比如下例可以直接调用
class Student(): def __init__(self,name,age): self.name = name self.age = age Student('xxx',18).name
除了静态类,还可以在类中指定一个类方法为类
听起来很绕,实际上就是在已有的类中,新建一个方法,但这个方法是被@classmethod
修饰的,并且返回一个类,看下例(嗯,下例是py2.7,为此尝试anaconda安装py2.7并尝试用conda install nb_conda_kernels
这样的方法安装jupyter,虽然有py2.7的这个kernel,但是无法打开,所以最后使用了conda create -n py27 python=2.7 ipykernel
语句来添加py2.7)
class Data_test2(object): day=0 month=0 year=0 def __init__(self,year=0,month=0,day=0): self.day=day self.month=month self.year=year @classmethod def get_date(cls, string_date): #这里第一个参数是cls, 表示调用当前的类名 year,month,day=map(int,string_date.split('-')) date1=cls(year,month,day) #返回的是一个初始化后的类 return date1 def out_date(self): print "year :" print self.year print "month :" print self.month print "day :" print self.day r=Data_test2.get_date("2016-8-1") r.out_date() """ year : 2016 month : 8 day : 1 """
python没有真正的抽象类,也可以使用abc来达到抽象类的效果