python 100天 (Day 6-15)

Update: 关于numpy和scipy,这里有一些总结

摘自Python - 100天从新手到大师,链接:https://github.com/jackfrued/Python-100-Days

Day 06 函数和模块的使用

python 不支持函数重载,因为我们在定义一个函数的时候可以让它有多种不同的使用方式,比如

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
from random import randint


def roll_dice(n=2):
"""摇色子"""
total = 0
for _ in range(n):
total += randint(1, 6)
return total


def add(a=0, b=0, c=0):
"""三个数相加"""
return a + b + c


# 如果没有指定参数那么使用默认值摇两颗色子
print(roll_dice())
# 摇三颗色子
print(roll_dice(3))
print(add())
print(add(1))
print(add(1, 2))
print(add(1, 2, 3))
# 传递参数时可以不按照设定的顺序进行传递
print(add(c=50, a=100, b=200))

在不确定参数个数的时候,我们可以使用可变参数:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
# 在参数名前面的*表示args是一个可变参数
def add(*args):
total = 0
for val in args:
total += val
return total


# 在调用add函数时可以传入0个或多个参数
print(add())
print(add(1))
print(add(1, 2))
print(add(1, 2, 3))
print(add(1, 3, 5, 7, 9))

然而,如果在同一个.py文件中定义了两个同名函数,由于Python没有函数重载的概念,那么后面的定义会覆盖之前的定义,也就意味着两个函数同名函数实际上只有一个是存在的。

因此,使用 from filename import functioname

需要说明的是,如果我们导入的模块除了定义函数之外还有可以执行代码,那么Python解释器在导入这个模块时就会执行这些代码,事实上我们可能并不希望如此,因此如果我们在模块中编写了执行代码,最好是将这些执行代码放入如下所示的条件中,这样的话除非直接运行该模块,if条件下的这些代码是不会执行的,因为只有直接执行的模块的名字才是”main“。

module3.py

1
2
3
4
5
6
7
8
9
10
11
12
13
def foo():
pass

def bar():
pass

# __name__是Python中一个隐含的变量它代表了模块的名字
# 只有被Python解释器直接执行的模块的名字才是__main__
if __name__ == '__main__':
print('call foo()')
foo()
print('call bar()')
bar()

python 中的交换赋值

1
2
3
4
5
6
def gcd(x, y):
"""求最大公约数"""
(x, y) = (y, x) if x > y else (x, y)
for factor in range(x, 0, -1):
if x % factor == 0 and y % factor == 0:
return factor

(讲真一般不是用辗转相除嘛…)

1
2
3
4
5
6
7
a, b = map(int, input("enter two numbers").split())  
c = a % b
while c :
a = b
b = c
c = a % b
print(b)

Day 07 字符串和常用数据结构

如果不希望字符串中的\表示转义,我们可以通过在字符串的最前面加上字母r来加以说明

1
2
3
s1 = r'\'hello, world!\''
s2 = r'\n\\hello, world!\\\n'
print(s1, s2, end='')

在Python中,我们还可以通过一系列的方法来完成对字符串的处理,代码如下所示:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
str1 = 'hello, world!'
# 通过内置函数len计算字符串的长度
print(len(str1)) # 13
# 获得字符串首字母大写的拷贝
print(str1.capitalize()) # Hello, world!
# 获得字符串每个单词首字母大写的拷贝
print(str1.title()) # Hello, World!
# 获得字符串变大写后的拷贝
print(str1.upper()) # HELLO, WORLD!
# 从字符串中查找子串所在位置
print(str1.find('or')) # 8
print(str1.find('shit')) # -1
# 与find类似但找不到子串时会引发异常
# print(str1.index('or'))
# print(str1.index('shit'))
# 检查字符串是否以指定的字符串开头
print(str1.startswith('He')) # False
print(str1.startswith('hel')) # True
# 检查字符串是否以指定的字符串结尾
print(str1.endswith('!')) # True
# 将字符串以指定的宽度居中并在两侧填充指定的字符
print(str1.center(50, '*'))
# 将字符串以指定的宽度靠右放置左侧填充指定的字符
print(str1.rjust(50, ' '))
str2 = 'abc123456'
# 检查字符串是否由数字构成
print(str2.isdigit()) # False
# 检查字符串是否以字母构成
print(str2.isalpha()) # False
# 检查字符串是否以数字和字母构成
print(str2.isalnum()) # True
str3 = ' jackfrued@126.com '
print(str3)
# 获得字符串修剪左右两侧空格之后的拷贝
print(str3.strip())

Python 支持格式化输出
Further information: https://www.geeksforgeeks.org/python-string-format-method

1
2
3
4
5
6
7
8
9
# 第一种
a, b = 5, 10
print('%d * %d = %d' % (a, b, a * b))
# 第二种
a, b = 5, 10
print('{0} * {1} = {2}'.format(a, b, a * b))
# 第三种
a, b = 5, 10
print(f'{a} * {b} = {a * b}')

Emunerate function

1
2
3
4
5
6
7
8
9
l1 = ["eat","sleep","repeat"]
s1 = "geek"
# creating enumerate objects
obj1 = enumerate(l1)
obj2 = enumerate(s1)
print ("Return type:",type(obj1)) # Return type: < type 'enumerate' >
print (list(enumerate(l1))) # [(0, 'eat'), (1, 'sleep'), (2, 'repeat')]
# changing start index to 2 from 0
print (list(enumerate(s1,2))) # [(2, 'g'), (3, 'e'), (4, 'e'), (5, 'k')]

sorted function

1
2
3
4
5
numbers = [4, 2, 12, 8]
sorted_numbers = sorted(numbers)
print(sorted_numbers)
# Output: [2, 4, 8, 12]
# 相较于list.sort(),这样做不会改变原先的list

生成式和生成器
使用生成式语法:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
import sys
f = [x for x in range(1, 10)]
print(f)
f = [x + y for x in 'ABCDE' for y in '1234567']
print(f)
# 用列表的生成表达式语法创建列表容器
# 用这种语法创建列表之后元素已经准备就绪所以需要耗费较多的内存空间
f = [x ** 2 for x in range(1, 1000)]
print(sys.getsizeof(f)) # 查看对象占用内存的字节数
print(f)
# 请注意下面的代码创建的不是一个列表而是一个生成器对象
# 通过生成器可以获取到数据但它不占用额外的空间存储数据
# 每次需要数据的时候就通过内部的运算得到数据(需要花费额外的时间)
f = (x ** 2 for x in range(1, 1000))
print(sys.getsizeof(f)) # 相比生成式生成器不占用存储数据的空间
print(f)
for val in f:
print(val)

使用yeild关键字将一个普通函数改造成生成器函数:

1
2
3
4
5
6
7
8
9
10
11
12
def fib(n):
a, b = 0, 1
for _ in range(n):
a, b = b, a + b
yield a

def main():
for val in fib(20):
print(val)

if __name__ == '__main__':
main()

关于if __name__ == '__main__',请看https://stackoverflow.com/questions/419163/what-does-if-name-main-do?page=2&tab=votes#tab-top

集合(set)
创建集合:

1
2
3
4
5
6
7
8
9
10
11
12
13
# 创建集合的字面量语法
set1 = {1, 2, 3, 3, 3, 2}
print(set1)
print('Length =', len(set1))

# 创建集合的构造器语法
set2 = set(range(1, 10))
set3 = set((1, 2, 3, 3, 2, 1))
print(set2, set3)

# 创建集合的推导式语法(推导式也可以用于推导集合)
set4 = {num for num in range(1, 100) if num % 3 == 0 or num % 5 == 0}
print(set4)

向集合添加元素和从集合删除元素:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
set1.add(4)
set1.add(5)
# 将元素 x 添加到集合 sst1 中,如果元素已存在,则不进行任何操作

set2.update([11, 12])
# 同样是添加元素,且参数可以是列表,元组,字典等

set2.discard(5)
# 移除集合中的元素,且如果元素不存在,不会发生错误

if 4 in set2:
set2.remove(4)
# 同样将元素 x 从集合 s 中移除,如果元素不存在,则会发生错误

print(set1, set2)

print(set3.pop())
# 随机删除集合中的一个元素

print(set3)

集合的成员、交集、并集、差集等运算:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
# 集合的交集、并集、差集、对称差运算
print(set1 & set2)
# print(set1.intersection(set2))
print(set1 | set2)
# print(set1.union(set2))
print(set1 - set2)
# print(set1.difference(set2))
print(set1 ^ set2)
# print(set1.symmetric_difference(set2))
# 不同时包含于set1和set2的元素

# 判断子集和超集
print(set2 <= set1)
# print(set2.issubset(set1))
print(set3 <= set1)
# print(set3.issubset(set1))
print(set1 >= set2)
# print(set1.issuperset(set2))
print(set1 >= set3)
# print(set1.issuperset(set3))

字典

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
# 创建字典的字面量语法
scores = {'骆昊': 95, '白元芳': 78, '狄仁杰': 82}
print(scores)

# 创建字典的构造器语法
items1 = dict(name = "John", age = 36, country = "Norway")

# 通过zip函数将两个序列压成字典
items2 = dict(zip(['a', 'b', 'c'], '123'))
# Output:{'a': '1', 'b': '2', 'c': '3'}

# 创建字典的推导式语法
items3 = {num: num ** 2 for num in range(1, 10)}
print(items1, items2, items3)

# 通过键可以获取字典中对应的值
print(scores['骆昊'])
print(scores['狄仁杰'])
# 对字典中所有键值对进行遍历
for key in scores:
print(f'{key}: {scores[key]}')
# 更新字典中的元素
scores['白元芳'] = 65
scores['诸葛王朗'] = 71
scores.update(冷面=67, 方启鹤=85)
print(scores)
if '武则天' in scores:
print(scores['武则天'])
print(scores.get('武则天'))
# get方法也是通过键获取对应的值,但是可以设置默认值,如果指定键的值不存在时,返回该默认值
print(scores.get('武则天', 60))

# 删除字典中的元素
print(scores.popitem())
print(scores.popitem())
# 删除最后一个元素

print(scores.pop('骆昊', 100))
# The pop() method removes the specified item from the dictionary.
# The value of the removed item is the return value of the pop() method
# defaultvalue is optional. A value to return if the specified key do not exist.
# If this parameter is not specified, and the no item with the specified key is found, an error is raised

# 清空字典
scores.clear()
print(scores)

练习摘录
1.设计一个函数返回给定文件名的后缀名:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
def get_suffix(filename, has_dot=False):
"""
获取文件名的后缀名

:param filename: 文件名
:param has_dot: 返回的后缀名是否需要带点
:return: 文件的后缀名
"""
pos = filename.rfind('.') # str.rfind(str, beg=0 end=len(string))返回字符串最后一次出现的位置,如果没有匹配项则返回-1
if 0 < pos < len(filename) - 1:
index = pos if has_dot else pos + 1
return filename[index:]
else:
return ''

2.计算指定的年月日是这一年的第几天

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
def is_leap_year(year):
"""
判断指定的年份是不是闰年

:param year: 年份
:return: 闰年返回True平年返回False
"""
return year % 4 == 0 and year % 100 != 0 or year % 400 == 0


def which_day(year, month, date):
"""
计算传入的日期是这一年的第几天

:param year: 年
:param month: 月
:param date: 日
:return: 第几天
"""
days_of_month = [
[31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31],
[31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31]
][is_leap_year(year)]
total = 0
for index in range(month - 1):
total += days_of_month[index]
return total + date


def main():
print(which_day(1980, 11, 28))
print(which_day(1981, 12, 31))
print(which_day(2018, 1, 1))
print(which_day(2016, 3, 1))


if __name__ == '__main__':
main()

这里其实有点没看懂list初始化的部分,搜了一下python还有一个itertools.compress()函数:

1
2
3
4
5
6
7
8
9
10
11
import itertools
import operator

Codes =['C', 'C++', 'Java', 'Python']
selectors = [False, False, False, True]

Best_Programming = itertools.compress(Codes, selectors)

for each in Best_Programming:
print(each)
# Output:Python

itertools— 为高效循环而创建迭代器的函数”
https://docs.python.org/zh-cn/3/library/itertools.html

Day 08 面向对象编程基础

在Python中,属性和方法的访问权限只有两种,也就是公开的和私有的,如果希望属性是私有的,在给属性命名时可以用两个下划线作为开头

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
class Test:

def __init__(self, foo):
self.__foo = foo

def __bar(self):
print(self.__foo)
print('__bar')


def main():
test = Test('hello')
# AttributeError: 'Test' object has no attribute '__bar'
test.__bar()
# AttributeError: 'Test' object has no attribute '__foo'
print(test.__foo)


if __name__ == "__main__":
main()

但是,Python并没有从语法上严格保证私有属性或方法的私密性,它只是给私有的属性和方法换了一个名字来妨碍对它们的访问,事实上如果你知道更换名字的规则仍然可以访问到它们:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
class Test:

def __init__(self, foo):
self.__foo = foo

def __bar(self):
print(self.__foo)
print('__bar')


def main():
test = Test('hello')
test._Test__bar()
print(test._Test__foo)


if __name__ == "__main__":
main()

在实际开发中,我们并不建议将属性设置为私有的,因为这会导致子类无法访问。所以大多数Python程序员会遵循一种命名惯例就是让属性名以下划线开头来表示属性是受保护的,本类之外的代码在访问这样的属性时应该要保持慎重。这种做法并不是语法上的规则,单下划线开头的属性和方法外界仍然是可以访问的,所以更多的时候它是一种暗示或隐喻

Day 09 面向对象进阶

函数装饰器
详见:https://www.runoob.com/w3cnote/python-func-decorators.html

关于*args,**kwargs,详见:https://www.geeksforgeeks.org/args-kwargs-python/#:~:text=The%20special%20syntax%20*args%20in,used%20with%20the%20word%20args.

使用@property包装器来包装属性的getter(访问器)和setter(修改器)方法,使得对属性的访问既安全又方便:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
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()

关于class(object): object is the mother of all classes in Python. Declaring it as a new-style class in Python2. https://stackoverflow.com/questions/7375595/class-with-object-as-a-parameter

__slots__魔法
Python是一门动态语言。通常,动态语言允许我们在程序运行时给对象绑定新的属性或方法,当然也可以对已经绑定的属性和方法进行解绑定。但是如果我们需要限定自定义类型的对象只能绑定某些属性,可以通过在类中定义__slots__变量来进行限定。需要注意的是__slots__的限定只对当前类的对象生效,对子类并不起任何作用。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
class Person(object):

# 限定Person对象只能绑定_name, _age和_gender属性
__slots__ = ('_name', '_age', '_gender')

def __init__(self, name, age):
self._name = name
self._age = age

@property
def name(self):
return self._name

@property
def age(self):
return self._age

@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('王大锤', 22)
person.play()
person._gender = '男'
# person._is_gay = True
# AttributeError: 'Person' object has no attribute '_is_gay'

静态方法和类方法
静态方法:可以在生成对象之前运行

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
from math import sqrt

class Triangle(object):

def __init__(self, a, b, c):
self._a = a
self._b = b
self._c = c

@staticmethod
def is_valid(a, b, c):
return a + b > c and b + c > a and a + c > b

def perimeter(self):
return self._a + self._b + self._c

def area(self):
half = self.perimeter() / 2
return sqrt(half * (half - self._a) *
(half - self._b) * (half - self._c))


def main():
a, b, c = 3, 4, 5
# 静态方法和类方法都是通过给类发消息来调用的
if Triangle.is_valid(a, b, c):
t = Triangle(a, b, c)
print(t.perimeter())
# 也可以通过给类发消息来调用对象方法但是要传入接收消息的对象作为参数
# print(Triangle.perimeter(t))
print(t.area())
# print(Triangle.area(t))
else:
print('无法构成三角形.')


if __name__ == '__main__':
main()

和静态方法比较类似,Python还可以在类中定义类方法,类方法的第一个参数约定名为cls,它代表的是当前类相关的信息的对象(类本身也是一个对象,有的地方也称之为类的元数据对象),通过这个参数我们可以获取和类相关的信息并且可以创建出类的对象
classmethod 修饰符对应的函数不需要实例化,不需要 self 参数,但第一个参数需要是表示自身类的 cls 参数,可以来调用类的属性,类的方法,实例化对象等。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
from time import time, localtime, sleep

class Clock(object):
"""数字时钟"""

def __init__(self, hour=0, minute=0, second=0):
self._hour = hour
self._minute = minute
self._second = second

@classmethod
def now(cls):
ctime = localtime(time())
return cls(ctime.tm_hour, ctime.tm_min, ctime.tm_sec)

def run(self):
"""走字"""
self._second += 1
if self._second == 60:
self._second = 0
self._minute += 1
if self._minute == 60:
self._minute = 0
self._hour += 1
if self._hour == 24:
self._hour = 0

def show(self):
"""显示时间"""
return '%02d:%02d:%02d' % \
(self._hour, self._minute, self._second)


def main():
# 通过类方法创建对象并获取系统时间
clock = Clock.now()
while True:
print(clock.show())
sleep(1)
clock.run()


if __name__ == '__main__':
main()

The time() function returns the number of seconds passed since epoch.
The localtime() function takes the number of seconds passed since epoch as an argument and returns struct_time in local time.

Attributes of struct_time:

1
2
3
4
5
6
7
8
9
#int tm_sec; /* 秒 – 取值区间为[0,59] */
#int tm_min; /* 分 - 取值区间为[0,59] */
#int tm_hour; /* 时 - 取值区间为[0,23] */
#int tm_mday; /* 一个月中的日期 - 取值区间为[1,31] */
#int tm_mon; /* 月份(从一月开始,0代表一月) - 取值区间为[0,11] */
#int tm_year; /* 年份,其值等于实际年份减去1900 */
#int tm_wday; /* 星期 – 取值区间为[0,6],其中0代表星期一,1代表星期二,以此类推 */
#int tm_yday; /* 从每年的1月1日开始的天数 – 取值区间为[0,365],其中0代表1月1日,1代表1月2日,以此类推 */
#int tm_isdst; /* 夏令时标识符,实行夏令时的时候,tm_isdst为正。不实行夏令时的时候,tm_isdst为0;不了解情况时,tm_isdst()为负。

Difference between static method and class method: https://stackoverflow.com/questions/136097/difference-between-staticmethod-and-classmethod

继承
注意__init__的部分

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
class Person(object):
"""人"""

def __init__(self, name, age):
self._name = name
self._age = age

@property
def name(self):
return self._name

@property
def age(self):
return self._age

@age.setter
def age(self, age):
self._age = age

def play(self):
print('%s正在愉快的玩耍.' % self._name)

def watch_av(self):
if self._age >= 18:
print('%s正在观看爱情动作片.' % self._name)
else:
print('%s只能观看《熊出没》.' % self._name)


class Student(Person):
"""学生"""

def __init__(self, name, age, grade):
super().__init__(name, age)
self._grade = grade

@property
def grade(self):
return self._grade

@grade.setter
def grade(self, grade):
self._grade = grade

def study(self, course):
print('%s的%s正在学习%s.' % (self._grade, self._name, course))


class Teacher(Person):
"""老师"""

def __init__(self, name, age, title):
super().__init__(name, age)
self._title = title

@property
def title(self):
return self._title

@title.setter
def title(self, title):
self._title = title

def teach(self, course):
print('%s%s正在讲%s.' % (self._name, self._title, course))


def main():
stu = Student('王大锤', 15, '初三')
stu.study('数学')
stu.watch_av()
t = Teacher('骆昊', 38, '砖家')
t.teach('Python程序设计')
t.watch_av()


if __name__ == '__main__':
main()

多态
Python从语法层面并没有像Java或C#那样提供对抽象类的支持,但是我们可以通过abc(Abstract Base Class)模块的ABCMeta元类和abstractmethod包装器来达到抽象类的效果,如果一个类中存在抽象方法那么这个类就不能够实例化(创建对象)。https://www.geeksforgeeks.org/abstract-base-class-abc-in-python

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37

from abc import ABCMeta, abstractmethod

class Pet(object, metaclass=ABCMeta):
"""宠物"""

def __init__(self, nickname):
self._nickname = nickname

@abstractmethod
def make_voice(self):
"""发出声音"""
pass


class Dog(Pet):
"""狗"""

def make_voice(self):
print('%s: 汪汪汪...' % self._nickname)


class Cat(Pet):
"""猫"""

def make_voice(self):
print('%s: 喵...喵...' % self._nickname)


def main():
pets = [Dog('旺财'), Cat('凯蒂'), Dog('大黄')]
for pet in pets:
pet.make_voice()


if __name__ == '__main__':
main()

str method
the __str__ method is called when the following functions are invoked on the object and return a string:

  • print()
  • str()
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    class MyClass:
    x = 0
    y = ""

    def __init__(self, anyNumber, anyString):
    self.x = anyNumber
    self.y = anyString
    def __str__ (self):
    return 'MyClass(x=' + str(self.x) + ' ,y=' + self.y + ')'
    myObject = MyClass(12345, "Hello")

    print(myObject.__str__())
    print(myObject)
    print(str(myObject))
    print(myObject.__repr__())

    #Output:
    #MyClass(x=12345 ,y=Hello)
    #MyClass(x=12345 ,y=Hello)
    #MyClass(x=12345 ,y=Hello)
    #<__main__.MyClass object at 0x7f90bcf5e1f0>

hasattr() method
Python hasattr() function is an inbuilt utility function, which is used to check if an object has the given named attribute and return true if present, else false.

1
2
3
4
5
6
7
8
9
10
11
12
class GfG(object):
name = "GeeksforGeeks"
age = 24

obj = GfG()

print("Does name exist ? " + str(hasattr(obj, 'name')))
print("Does motto exist ? " + str(hasattr(obj, 'motto')))

#Output
#Does name exist ? True
#Does motto exist ? False

isinstance() method
Python isinstance() function returns True if the object is specified types, and it will not match then return False.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
test_int = 5
test_list = [1, 2, 3]


print("Is test_int integer? : " + str(isinstance(test_int, int)))
print("Is test_int string? : " + str(isinstance(test_int, str)))
print("Is test_list integer? : " + str(isinstance(test_list, int)))
print("Is test_list list? : " + str(isinstance(test_list, list)))

# testing with tuple
print("Is test_int integer or list or string? : "
+ str(isinstance(test_int, (list, int))))

#Output:
#Is test_int integer? : True
#Is test_int string? : False
#Is test_list integer? : False
#Is test_list list? : True
#Is test_int integer or list or string? : True

getattr()

1
2
3
4
5
6
7
8
9
10
11
12
13
>>>class A(object):
... bar = 1
...
>>> a = A()
>>> getattr(a, 'bar') # 获取属性 bar 值
1
>>> getattr(a, 'bar2') # 属性 bar2 不存在,触发异常
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: 'A' object has no attribute 'bar2'
>>> getattr(a, 'bar2', 3) # 属性 bar2 不存在,但设置了默认值
3
>>>

Day10 图形用户界面和游戏开发

nonlocal keyword

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27

def geek_func():

# local variable to geek_func
geek_name = "geek"
# Inner function

def geek_func2():

# Declaring nonlocal variable
nonlocal geek_name
geek_name = 'GeekForGeeks'

# Printing our variable
print(geek_name)

# Calling inner function
geek_func2()

# Printing local variable
print(geek_name)

geek_func()

#Output:
#GeekForGeeks
#GeekForGeeks

详见:https://blog.csdn.net/xCyansun/article/details/79672634

@unique
@unique is a class decorator specifically for enumerations. It searches an enumeration’s members gathering any aliases it finds; if any are found ValueError is raised with the details.
Basically, it raises an error if there are any duplicate enumeration values.

1
2
3
4
5
6
7
8
9
10
from enum import unique, Enum

@unique
class Mistake(Enum):
ONE = 1
TWO = 2
THREE = 3
FOUR = 3
#Output:
#ValueError: duplicate values found in <enum 'Mistake'>: FOUR -> THREE

这里的Enum跟c中作用类似

这次讲的内容感觉跟海龟绘图差不多,因为大一上学过了所以只贴一个链接:https://github.com/jackfrued/Python-100-Days/blob/master/Day01-15/10。%E5%9B%BE%E5%BD%A2%E7%94%A8%E6%88%B7%E7%95%8C%E9%9D%A2%E5%92%8C%E6%B8%B8%E6%88%8F%E5%BC%80%E5%8F%91.md

Day 11 文件和异常

在Python中实现文件的读写操作其实非常简单,通过Python内置的open函数,我们可以指定文件名、操作模式、编码信息等来获得操作文件的对象,接下来就可以对文件进行读写操作了。这里所说的操作模式是指要打开什么样的文件(字符文件还是二进制文件)以及做什么样的操作(读、写还是追加),具体的如下表所示。

操作模式 具体含义
'r' 读取 (默认)
'w' 写入(会先截断之前的内容)
'x' 写入,如果文件已经存在会产生异常
'a' 追加,将内容写入到已有文件的末尾
'b' 二进制模式
't' 文本模式(默认)
'+' 更新(既可以读又可以写)

操作模式

读写文本文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
def main():
f = None
try:
f = open('致橡树.txt', 'r', encoding='utf-8')
print(f.read())
except FileNotFoundError:
print('无法打开指定的文件!')
except LookupError:
print('指定了未知的编码!')
except UnicodeDecodeError:
print('读取文件时解码错误!')
finally:
if f:
f.close()


if __name__ == '__main__':
main()

在Python中,我们可以将那些在运行时可能会出现状况的代码放在try代码块中,在try代码块的后面可以跟上一个或多个except来捕获可能出现的异常状况。例如在上面读取文件的过程中,文件找不到会引发FileNotFoundError,指定了未知的编码会引发LookupError,而如果读取文件时无法按指定方式解码会引发UnicodeDecodeError,我们在try后面跟上了三个except分别处理这三种不同的异常状况。最后我们使用finally代码块来关闭打开的文件,释放掉程序中获取的外部资源,由于finally块的代码不论程序正常还是异常都会执行到(甚至是调用了sys模块的exit函数退出Python环境,finally块都会被执行,因为exit函数实质上是引发了SystemExit异常),因此我们通常把finally块称为“总是执行代码块”,它最适合用来做释放外部资源的操作。如果不愿意在finally代码块中关闭文件对象释放资源,也可以使用上下文语法,通过with关键字指定文件对象的上下文环境并在离开上下文环境时自动释放文件资源,代码如下所示。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
def main():
try:
with open('致橡树.txt', 'r', encoding='utf-8') as f:
print(f.read())
except FileNotFoundError:
print('无法打开指定的文件!')
except LookupError:
print('指定了未知的编码!')
except UnicodeDecodeError:
print('读取文件时解码错误!')


if __name__ == '__main__':
main()

yeild

Supporting the “with” statement in user defined objects: https://www.geeksforgeeks.org/with-statement-in-python/

Powered by Hexo

Copyright © 2013 - 2023 骸骨长廊 All Rights Reserved.

UV : | PV :