python基本语法

python 基本语法

if

1
2
3
4
5
6
# if语句
age = 15
if age>16:
print('可以进入')
else:
print('禁止进入')

if-elif-else 语句

1
2
3
4
5
6
7
8
9
10
11
12
# if-elif-else 语句
score = 50
if score>=90:
print('A')
elif score>=80:
print('B')
elif score>=70:
print('C')
elif score>=60:
print('D')
else:
print('不通过')

for 和while

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
# for 遍历
for i in range(1,5):# 不包括10
print(i)
for i in range(1,5,2):
print(i)

for item in ['Mosh','John','Sarah']:
print(item)

# while 遍历
n=1
while n<10:
print(n)
n=n+1
else:
print('循环结束')
# for循环嵌套
for i in range(1,10):
for j in range(1,i+1):
# 默认是换行结束的,这里告诉他end=' '以空格结束
print(f'{i}*{j}={i*j}',end=' ')
print()# 换行,
# while嵌套
n=1
while n<10:
m=1
while m<=n:
print(f'{n}*{m}={n * m}', end=' ')
m=m+1
n=n+1
print()
# while 和for 是可以混合使用的
# while ,for 和 else也是可以一起使用的

break和continue

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
# break
while True:
s = input('输入:(0)退出:')
if s=='0':
break
print('您输入的是',s)

# continue
for s in 'python':
if s=='y':
continue
print(s,end='')
# 猜数字
import random
target = random.randint(1,100)
i = 1
while i<=3:
i = i+1
n =int(input('请猜想一个1-100的整数'))
if n>target:
print('猜大了')
elif n<target:
print('猜小了')
else:
print('猜对了')
break
print('傻逼,猜了三次都没对')
print('傻逼,猜了三次都没对')
print('傻逼,猜了三次都没对')

数字

分为 int 和 float两种

运算符

数学运算符

1
2
3
10**3	#幂运算 10^3
10+=3 #和C++一样
10-=3

逻辑运算符

1
2
3
and #和
or #或
not #非

比较运算符

1
2
3
4
5
>
<
>=
<=
==

math function

1
2
round()	#四舍五入
abs() #绝对值

math 模块

1
2
math.ceil(x)	# 取大于x的最小整数
math.floor(x) # 取小于x的最大整数

字符串

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
# 字符串
# 1.单引号或者双引号
# 2.单三引号或者双三引号
print('''




''')
# 转义字符
print('这里\n\n\n\n\n\n\n有好几个换行')
print('这里\t\t\t\t有好几个tab键')
# 字符串索引
s = '床前明月光'
print(s[0])
print(s[1])
print(s[2])
print(s[3])
print(s[4])

# 负的索引,即右往左遍历
print(s[-1])
print(s[-2])
print(s[-3])
print(s[-4])
print(s[-5])

# 字符串切片
# 'string'.[begin:end:pace]默认步长为1
# 不会包含end,但会包含begin
s = '床前明月光!'
print(s[1:5:2])
# 从1开始到结尾
print(s[1:])
# 从开始到这里
print(s[:3])

# 格式化输出 format()
user_1 = '韩梅梅'
user_2 = '李雷'
print(f'{user_1}{user_2}说:hello,傻逼')
# + 号连接多个字符串
print('are'+' you'+' ok')

replace()实现字符串替换

replace(‘’,’’,)前面是待替换的字符串,后面是替换的内容。最后一个可选可不选。是在替换的内容选择前几位替换进去。

替换结果时找到字符串中所有的目标进行替换

slice()字符串切片

split()分割和join()合并

split()可以基于指定分隔符将字符串分隔成多个子字符串(存储到列表中)。如果不指定分隔符,则默认使用空白字符(换行符/空格/制表符)。示例代码如下:

1
2
a = "to be or not to be"
print(a.split())

[‘to’, ‘be’, ‘or’, ‘not’, ‘to’, ‘be’]

join()的作用和split()作用刚好相反,用于将一系列子字符串连接起来。示例代码如下:

1
2
a = ['sxt','sxt100','sxt200']
print('x'.join(a))

sxt-sxt100-sxt200

拼接字符串要点:
使用字符串拼接符+,会生成新的字符串对象,因此不推荐使用+来拼接字符串。推荐使用join 函数,因为join 函数在拼接字符串之前会计算所有字符串的长度,然后逐一拷贝,仅新建一次对象。

字符串汇总

常用查找方法

a.isalnum,a.isalpha,可以是对a这个整个字符串,也可以是a[1],a[1:4]等等字符串切片

去除首尾信息

我们可以通过strip()去除字符串首尾指定信息。通过lstrip()去除字符串左边指定信息,rstrip()去除字符串右边指定信息。

1
2
3
4
5
6
7
8
>>> "*s*x*t*".strip("*")
's*x*t'
>>> "*s*x*t*".lstrip("*")
's*x*t*'
>>> "*s*x*t*".rstrip("*")
'*s*x*t'
>>> " sxt ".strip()
'sxt'
大小写转换

编程中关于字符串大小写转换的情况,经常遇到。我们将相关方法汇总到这里。为了方便学习,先设定一个测试变量:a = “gaoqi love programming, love SXT”

其他方法
  1. isalnum() 是否为字母或数字
  2. isalpha() 检测字符串是否只由字母组成(含汉字)。
  3. isdigit() 检测字符串是否只由数字组成。
  4. isspace() 检测是否为空白符
  5. isupper() 是否为大写字母
  6. islower() 是否为小写字母
  7. in 判断字符串中是否有我们的目标
数字格式化

字符串格式化

%s
%10s——右对齐,占位符10位
%-10s——左对齐,占位符10位
%.2s——截取2位字符串
%10.2s——10位占位符,截取两位字符串

python格式化输出

列表

1
2
3
4
5
6
7
8
9
10
11
12
13
# 列表
# 可以直接通过列表索引修改元素
my_list = [1,2,'a','awserq3',1.3]
my_list.pop(1)# 把my_list[i]出列
my_list.pop()# 把my_list最后一个元素出列
my_list.remove('a')# 直接把a这个元素移除
my_list.append(222)# 添加元素,加到队尾
my_list.append('python')# 添加元素,加到队尾
my_list.insert(2,'java')# 现在my_list[2]就是java
my_list.extend('CPP')# 把字符串 按位拆开插入尾部
my_list.extend('6789')# 直接6789 的话是不行的。不可迭代
my_list.extend([12,34,56])
print(my_list)

列表:用于存储任意数目、任意类型的数据集合。
列表是内置可变序列,是包含多个元素的有序连续的内存空间。列表定义的标准语法格式:

a = [10,20,30,40]
其中,10,20,30,40 这些称为:列表a 的元素。
列表中的元素可以各不相同,可以是任意类型。比如:
a = [10,20,’abc’,True]

遍历列表

直接遍历,输出数值

1
2
3
numbers = [2,2,4,6,3,4,6,1]
for number in numbers:
print(number)

通过枚举输出,返回元组

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
numbers = [2,2,4,6,3,4,6,1]

for number in enumerate(numbers):
print(number)

'''
输出结果
(0, 2)
(1, 2)
(2, 4)
(3, 6)
(4, 3)
(5, 4)
(6, 6)
(7, 1)
'''

还可以输出去掉括号的枚举内容

1
2
3
4
letters = ["a","b","c"]

for index,letter in enumerate(letters):
print(index,letter)

找到列表中的最大值

1
2
3
4
5
6
number = [12,3,289,33,2903,948,1029]
max = number[0]
for item in number:
if item>max:
max = item
print(f'max number is {max}')

二维列表(矩阵)

1
2
3
4
5
6
matrix = [
[1,2,3],
[4,5,6],
[7,8,9]
]
matrix[0][0]

列表去重

1
2
3
4
5
6
numbers = [2,2,4,6,3,4,6,1]
uniques = []
for number in numbers:
if number not in uniques:
uniques.append(number)
print(uniques)

列表解释

1
2
3
4
5
6
7
8
9
10
11
12
items =[
("product1",10),
("product2",9),
("product3",12),
]
# 如果用lambda函数和map遍历
prices = map(lambda item:item[1],items)
# 但是用列表解释的话
prices = [ item[1] for item in items] # 输出[10, 9, 12]
prices = [ item[1]>=10 for item in items ] # 输出[True, False, True]
filtered = [item for item in items if[item[1]>=10]]
# 输出[('product1', 10), ('product3', 12)]

元组 Tuple

只有 count和index两个方法

1
2
3
4
5
# 元组,(不可变的列表)用小括号
# 不能加减元素
my_list = (1,2,'a',1.2)
my_list[2]=22
# 这样是会报错的

字典

1
2
3
4
5
6
7
8
9
10
11
12
# 字典{}
# 键值对 key->value
user = {
'name':'Tom',
'age': 18,
'gender': 'male'
}
print(user)
user['age'] = 28
print(user['age'])
user['inte'] = '打篮球'
print(user)

输出电话号码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
number = {
'1' : 'One',
'2' : 'Two',
'3' : 'Three',
'4' : 'Four',
'5' : 'Five',
'6' : 'Six',
'7' : 'Seven',
'8' : 'Eight',
'9' : 'Nine',
'0' : 'Zero'
}
phone = input('Phone: ')
for n in phone:
print(number[n],end=' ')

emoji

1
2
3
4
5
6
7
8
9
10
message = input(">")
words = message.split(' ')
emojis = {
":)":"😄",
":(":"☹"
}
output = ""
for word in words:
output+= emojis.get(word,word)+" "
print(output)

get的用法

dic.get(k,d) 的意思是说哈,再字典中找,找到了呢就返回dic[k],找不到呢就返回d

函数

def是关键词

1
2
3
4
5
6
7
8
def sum(n,m):
s=0
while n<=m:
s+=n
n+=1
return s

print(sum(1,100))

函数返回值,不写默认返回None

推荐要有返回值,在外面输出,后期代码维护方便

1
2
3
4
5
6
7
def square(number):
print(number**2)
return number**2

print(square(3))
# 输出 9,9
# 调用函数输出一遍,返回又输出一遍

key arguments

1
2
3
def increment(number,by)
return number+by
print(increment(number=2,by=1))# 通过指定number=,by=,增加代码的可读性

缺省参数

默认参数应该放在参数列表中的最后一位

形如def increment(number,by =1 ,anothor)的写法是不能接受的

1
2
3
def increment(number,by=1)
return number+by
print(increment(2))# 这里如果我不传入参数,那么缺省的by 就等于1

*args

运用*args,可以传入很多的参数

1
2
3
4
5
6
def multiply(*numbers):
total = 1
for number in numbers:
total *= number
return total
print(multiply(2,3,4,5))# 输出 120

**args

传入多个参数,其中是可以指定每个参数的类型的

1
2
3
4
def save_user(**user):
print(user)
print(user['name'])
save_user(id=1,name='John',age = 22)

全局变量和局部变量

1
2
3
4
5
6
7
8
9
message = "a"

def greet():
message = "b"
return message

greet()
print(message) # 还是a,因为这里的message时全局变量
print(greet.message)# b,因为接受了一个局部变量

可以通过关键字global 把函数中的局部变量转换成全局变量

1
2
3
4
5
6
7
8
message = "a"

def greet():
global message
message = "b"

greet()
print(message)

Lambda Function

Lambda函数又叫做匿名函数

lambda 并不会带来程序运行效率的提高,只会使代码更简洁。

如果使用lambda,lambda内不要包含循环,如果有,我宁愿定义函数来完成,使代码获得可重用性和更好的可读性。

总结:lambda 是为了减少单行函数的定义而存在的。

1
2
3
4
g = lambda x:x+1
# 等价于
def g(x):
return x+1

又如

1
2
3
4
5
6
7
def sort_item(item):
return item[1]

items.sort(key=sort_item)
# 用lambda函数重写
# 上面的三行就简化成了一行
items.sort(key=lambda item:item[1])

所以Lambda函数的写法就是

1
lambda paramerters:expression

Map function

map()是 python 内置的高阶函数,它接收一个函数 f 和一个 list,并通过把函数 f 依次作用在 list 的每个元素上,得到一个新的列表并返回。

map()的使用方法形如map(f(x),Itera),它有两个参数,第一个参数为某个函数,第二个为可迭代对象。

1
2
3
4
5
6
7
8
9
10
11
items =[
("product1",10),
("product2",9),
("product3",12),
]
# 我们只对后面的数字感兴趣,要输出数字
# 那么我们就输出每个 item中的第二个元素,也就是item[1]
# 那么这里map函数当中的第一个参素是一个lambda函数,返回的是item中的第二个元素
# 第二个参数就是我们的可迭代对象列表items,然后map会自动遍历items
x = map(lambda item:item[1],items)
print(list(x)) # 输出 [10,9,12]

Filter Function

和map函数一样的格式,第一个参数传入一个函数,第二个参数传入一个可迭代的对象

filter函数用来筛选

1
2
3
4
5
6
7
8
items =[
("product1",10),
("product2",9),
("product3",12),
]
filtered = list(filter(lambda item : item[1]>=10, items))
print(filtered)
# 输出结果[('product1', 10), ('product3', 12)]

Zip Function

1
2
3
4
5
list1 = [1,2,3]
list2 = [10,20,30]
# [(1,10),(2,20),(3,30)]
print(list(zip("abc",list1,list2)))
# 输出[('a', 1, 10), ('b', 2, 20), ('c', 3, 30)]

if __name__ \=\= \’__main__\’

https://blog.csdn.net/yjk13703623757/article/details/77918633/

通俗的理解__name__ == '__main__':假如你叫小明.py,在朋友眼中,你是小明(__name__ == '小明');在你自己眼中,你是你自己(__name__ == '__main__')

if __name__ == '__main__'的意思是:当.py文件被直接运行时,if __name__ == '__main__'之下的代码块将被运行;当.py文件以模块形式被导入时,if __name__ == '__main__'之下的代码块不被运行。

python基本语法

Exception :异常

异常会发现你的错误并报告,而不是说让你的程序down掉

1
2
3
4
5
6
7
8
9
10
11
try:
age = int(input('Age : '))
income = 2000
risk = income/age
print(age)
except ZeroDivisionError:
print('Age cannot be 0.')
except ValueError:
print('Invalid value')
finally:
print('Oui')

finally后面的代码是操作成功后执行的代码

Raise exception

相当于C++中的 throw,抛出一个异常来

当程序出现错误,python会自动引发异常,也可以通过raise显示地引发异常。一旦执行了raise语句,raise后面的语句将不能执行。也就是自定义的异常情况

1
2
3
4
5
6
7
8
try:
s = None
if s is None:
print "s 是空对象"
raise NameError #如果引发NameError异常,后面的代码将不能执行
print len(s) #这句不会执行,但是后面的except还是会走到
except TypeError:
print "空对象没有长度"

又如

1
2
3
4
5
6
7
8
9
def calculate_xfactor(age):
if age<=0:
raise ValueError("Age cannot be 0 or less.")
return 10/age

try:
calculate_xfactor(-1)
except ValueError as error:
Print(error)

Cost of Raising Exceptions

使用raise是要多出很多时间的

with 语句

凡是对象带

1
__enter__ 和 __exit__

这两个magic function的,都可以用with语句,它会自动打开关闭这个文件。

所以不再需要Finally这个关键字了

而且with可以同时打开很多文件

1
2
3
4
5
6
7
8
9
try:
with open("1.py") as file,open("anather.txt") as target:
print("File opened")
age = int(input("Age: "))
xfactor = 10/age
except (ValueError,ZeroDivisionError):
print("You didn't enter a valid age")
else:
print("No exceptions were thrown")

类和对象

类的每一个单词首字母都要大写

1
2
3
4
5
6
class Point:
def move(self):
print("move")

def draw(self):
print("draw")

声明了一个实例后,还可以通过. 运算符添加这个实例的属性

构造函数

1
def __init__(self):
例一
1
2
3
4
5
6
7
8
9
10
11
12
13
class Person:
def __init__(self,name):
self.name = name

def talk(self):
print(f"Hi,i am {self.name}")
Jason = Person('Jason')

Jason.talk()
print(Jason.name)

bob = Person('Bob')
bob.talk()
例二
1
2
3
4
5
6
7
8
9
10
11
12
13
14
# 类和对象:面向对象 编程
class Person:
def __init__(self,name,sex,birthday):
self.name = name
self.sex = sex
self.birthday = birthday
# self 相当于js中的this
def say(self,word):
print(f'{self.name}说:"{word}"')

zhang_San = Person('张三','male','2001')
li_si = Person('李四','male','2000')
zhang_San.say("我是你爹")
li_si = Person("GUN!!")

classmethod,staticmethod修饰符和类方法的总结

classmethod
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
class A(object):

# 属性默认为类属性(可以给直接被类本身调用)
num = "类属性"

# 实例化方法(必须实例化类之后才能被调用)
def func1(self): # self : 表示实例化类后的地址id
print("func1")
print(self)

# 类方法(不需要实例化类就可以被类本身调用)
@classmethod
def func2(cls): # cls : 表示没用被实例化的类本身
print("func2")
print(cls)
print(cls.num)
cls().func1()

# 不传递传递默认self参数的方法(该方法也是可以直接被类调用的,但是这样做不标准),pycharm红线
def func3():
print("func3")
print(A.num) # 属性是可以直接用类本身调用的

# A.func1() 这样调用是会报错:因为func1()调用时需要默认传递实例化类后的地址id参数,如果不实例化类是无法调用的
A.func2()
A.func3()

又如:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
class Point:
def __init__(self ,x,y):
self.x=x
self.y=y
@classmethod
def zero(cls):
pass
return cls(0,0)

def draw(self):
print(f"Point({self.x},{self.y})")
# point = Point(0,0)
point = Point.zero()# 这两行代码,是等价的
point.draw()
staticmethod
总结

实例方法只能被实例对象调用,静态方法(由@staticmethod装饰的方法)、类方法(由@classmethod装饰的方法),可以被类或类的实例对象调用。

实例方法,第一个参数必须要默认传实例对象,一般习惯用self。

静态方法,参数没有要求。

类方法,第一个参数必须要默认传类,一般习惯用cls

Privite Members 私有成员,外界无法访问

设为私有的方法,就是在属性前加两条下划线

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
class TagCloud:
def __init__(self):
self.__tags = {}

def add(self, tag):
self.__tags[tag.lower()] = self.__tags.get(tag.lower(), 0) + 1

def __getitem__(self, tag):
return self.__tags.get(tag.lower(), 0)

# get方法,在字典中查询,查到了返回对应值,这里就是tags出现的数量,查不到就返回0

def __setitem__(self, tag, count):
self.__tags[tag.lower()] = count

def __len__(self):
return len(self.__tags)

def __iter__(self):
return iter(self.__tags)

cloud = TagCloud()
print(len(cloud))

cloud.add("Python")
cloud.add("Python")
cloud.add("python")
cloud.add("Java")
cloud.add("C#")

print(cloud.__tags)# 报错

但是我们还是有方法获取到类内的属性

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
class TagCloud:
def __init__(self):
self.__tags = {}

def add(self, tag):
self.__tags[tag.lower()] = self.__tags.get(tag.lower(), 0) + 1

def __getitem__(self, tag):
return self.__tags.get(tag.lower(), 0)

# get方法,在字典中查询,查到了返回对应值,这里就是tags出现的数量,查不到就返回0

def __setitem__(self, tag, count):
self.__tags[tag.lower()] = count

def __len__(self):
return len(self.__tags)

def __iter__(self):
return iter(self.__tags)

cloud = TagCloud()
print(len(cloud))

cloud.add("Python")
cloud.add("Python")
cloud.add("python")
cloud.add("Java")
cloud.add("C#")

print(cloud.__dict__) # 这样就会显示了
print(cloud.__TagCloud__tags) # 这样就会显示了

magic function

csdn上比较全的指南

1
2
3
4
5
6
7
8
9
10
11
12
13
class Point:
def __init__(self ,x,y):
self.x=x
self.y=y

def __str__(self):
return f"({self.x},{self.y})"

def draw(self):
print(f"Point({self.x},{self.y})")

point = Point(1,2)
print(point.__str__()) # 输出(1,2)
魔术方法中的比较函数
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
class Point:
def __init__(self ,x,y):
self.x=x
self.y=y

def __eq__(self,other):
return self.x == other.x and self.y == other.y

def __gt__(self,other):
return self.x > other.x and self.y > other.y

point = Point(10,20)
other = Point(1,2)
print(point.__eq__(other)) # false
print(point.__gt__(other)) # true
魔术方法中的运算函数
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
class Point:
def __init__(self, x, y):
self.x = x
self.y = y

def __add__(self, other):
return Point(self.x + other.x, self.y + other.y)

def __gt__(self, other):
return self.x > other.x and self.y > other.y


point = Point(10, 20)
other = Point(1, 2)
print(f"point is ({point.__add__(other).x},{point.__add__(other).y})") # (11,22)
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
class TagCloud:
def __init__(self):
self.tags = {}

def add(self,tag):
self.tags[tag.lower()]=self.tags.get(tag.lower(),0)+1

def __getitem__(self, tag):
return self.tags.get(tag.lower(),0)
# get方法,在字典中查询,查到了返回对应值,这里就是tags出现的数量,查不到就返回0

def __setitem__(self, tag, count):
self.tags[tag.lower()] = count

def __len__(self):
return len(self.tags)

def __iter__(self):
return iter(self.tags)

cloud = TagCloud()
cloud["python"] = 10

print(len(cloud))
cloud.add("Python")
cloud.add("Python")
cloud.add("python")
cloud.add("Java")
cloud.add("C#")
print(cloud.tags) #{'python': 13, 'java': 1, 'c#': 1}
print(cloud.__getitem__("python")) #13
print(cloud.__len__()) #3

property

property() 函数的作用是在新式类中返回属性值。

在绑定属性时,如果我们直接把属性暴露出去,虽然写起来很简单,但是,没办法检查参数,导致可以把成绩随便改。这显然不合逻辑,为了限制score的范围,可以通过一个set_score()方法来设置成绩,再通过一个get_score()来获取成绩,这样,在set_score()方法里,就可以检查参数:

class property( fget , fset , fdel , doc )

参数:

  • fget — 获取属性值的函数
  • fset — 设置属性值的函数
  • fdel — 删除属性值函数
  • doc — 属性描述信息
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
class Product:
def __init__(self,price):
self.__price = price

def get_price(self):
return self.__price

def set_price(self,value):
if value<0:
raise ValueError("Price can not be negative")
self.__price = value

price = property(get_price,set_price)

product = Product(10)
print(product.price) # 写了property之后,类外就能访问类内属性了

但这样,类外还是能访问到我们的get_price,set_price方法,那么如果我们要在类外无法访问这两个方法,就要用到@property

@property修饰符

有没有既检查参数,又可以用类似属性这样简单的方式来访问类的变量呢,当然有

还记得装饰器可以给函数动态加上功能吗,对于类的方法,装饰器一样起作用,python内置的property装饰器就是负责把一个方法变成属性调用的

将 property 函数用作装饰器可以很方便的创建只读属性:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
class Product:
def __init__(self,price):
self.price = price

@property
def price(self):
return self.__price

@price.setter
def price(self,value):
if value<0:
raise ValueError("Price can not be negative")
self.__price = value


product = Product(10)
print(product.price)

@property的实现比较复杂,我们先考察如何使用,把一个getter方法变成属性,只需要加上@property就可以了,此时,@property本身又创建了另一个装饰器@price.setter,负责把一个setter方法变成属性赋值,于是,我们就拥有一个可控的属性操作

注意到这个神奇的@property,我们在对实例属性操作的时候,就知道该属性很可能不是直接暴露的,而是通过getter和setter方法来实现的

还可以定义只读属性,只定义getter方法,不定义setter方法就是一个只读属性,这时候再尝试修改,就会报错了

继承

在字类的括号中写父类即可

1
2
3
4
5
6
7
8
9
10
11
12
13
14
class Mammal:
def walk(self):
print("walk")

class Dog(Mammal):
pass #python是不接受空类的,所以在这里写pass代表这个类里什么都没有
class Cat(Mammal):
def be_annoying(self):
print("annoying")

cat1 = Cay()
cat1.be_annoying()
dog1 = Dog()
dog1.walk()

和其他语言的类一样,可以自己添加功能,类的属性

Object对象

所有的类都继承于Object对象。而且继承了Object对象中的magic function

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
class Animal(object):# 这里写不写(Object)都是可以的
def __init__(self):
self.age = 1

def eat(self):
print('eat')

class Mammal(Animal):
def __init__(self):
pass

m = Mammal()
print(isinstance(m,object)) #true
print(isinstance(m,Animal)) #true
print(issubclass(Mammal,object)) #true

和js中差不多,Object是总类,Animal继承 Object ,Mammal继承Animal

super().__int__()

当需要继承父类构造函数中的内容,且子类需要在父类的基础上补充时,使用super().__init__()方法

1
2
3
4
5
6
7
8
9
10
11
12
13
class Animal(object): # 这里写不写(Object)都是可以的
def __init__(self):
print("Animal Constructor")
self.age = 1

def eat(self):
print('eat')

class Mammal(Animal):
def __init__(self):
super().__init__()
print("Mammal Constructor")
self.weight = 2

Multi-level inheritance

多级继承会增加复杂度,还会继承意想不到的方法

1
2
3
4
5
6
7
8
9
10
class Animal:
def eat(self):
print("eat")

class Bird(Animal):
def fly(self):
print("fly")

class Chick(Animal):
pass

Multiple inheritance

一个子类继承多个父类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
class Employee:
def greet(self):
print("Employee Greet")

class Person:
def greet(self):
print("Person Greet")

class Manager(Employee,Person):
pass

manager = Manager()
manager.greet() # 输出Employee Greet
# 先继承谁的,就输出谁的方法

A Good Example of inheritance

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
class InvalidOperationError(Exception):
pass

class Stream:
def __init__(self):
self.opened = False

def open(self):
if self.opened:
raise InvalidOperationError("Stream is alread open")
self.opened = True

def close(self):
if not self.opened:
raise InvalidOperationError("Stream is alread closed")
self.opened = False

class FileStream(Stream):
def read(self):
print("Reading data from a file")

class NetworkStream(Stream):
def read(self):
print("Reading data from a network")

多态

Abstract Base Classes

由于python 没有抽象类、接口的概念,所以要实现这种功能得abc.py 这个类库

@abstractmethod:抽象方法,含abstractmethod方法的类不能实例化,继承了含abstractmethod方法的子类必须复写所有abstractmethod装饰的方法,未被装饰的可以不重写

实例化抽象类,会报错

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
from abc import ABC,abstractmethod
class Stream(ABC):
def __init__(self):
self.opened = False

@abstractmethod
def read(self):
pass

class FileStream(Stream):
pass


class NetworkStream(Stream):
def read(self):
print("Reading data from a network")

stream1 = NetworkStream()
stream1.read() # 没毛病,输出Reading data from a network
stream2 = FileStream()
stream2.read() # 报错

实现多态

就是自类对父类函数的重写,从而让一个函数是现在不同类中的不同功能

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
from abc import ABC,abstractmethod

class UIControl(ABC):
@abstractmethod
def draw(self): # 这是虚基类
pass

class TextBox(UIControl):
def draw(self):
print("TextBox")

class DropDownList(UIControl):
def draw(self):
print("DropDownList")

def draw(controls): # 通过这个函数能更明显的体现多态的功能
for control in controls:
control.draw()

ddl = DropDownList()
textbox = TextBox()
print(isinstance(ddl,UIControl)) # 输出ddl是否为UIControl的子类
draw([ddl,textbox]) # 输出结果是 DropDownList 和 TextBox

python中的鸭式辩型

  • 像鸭子一样走路,有用并且嘎嘎叫的鸟就是鸭子
  • 哪怕并不是从鸭子类的原型对象继承而来,但认为这个对象是鸭子

所以向上面的draw(controls)函数,他并不要求输入的对象是从哪个类实例化出来的。也并不要求这个类是从哪个基类继承的这个draw()方法,他只要求这个类中有一个draw()函数即可,这就是鸭式辩型。所以说,我们完全可以不写UIcontrol这个虚基类,因为python和JavaScript一样支持鸭式辩型

Data classes:collections模块的namedtuple子类

当我们构建一个Point类实例化出来两个对象的时候,不能直接判断他们是否相等.在C++中,我们需要进行==重载,但是在python中,我们需要用__eq__ 这个magic function或者 Data classes来实现这个功能

1
2
3
4
5
6
7
8
9
10
11
class Point:
def __init__(self,x,y):
self.x = x
self.y = y

def __eq__(self, other):
return self.x == other.x and self.y==other.y

p1 = Point(1,2)
p2 = Point(1,2)
print(p1==p2)

当然,data class 的方法更加简单

collections模块的namedtuple子类不仅可以使用item的index访问item,还可以通过item的name进行访问。可以将namedtuple理解为c中的struct结构,其首先将各个item命名,然后对每个item赋予数据。

collections.namedtuple(typename, field_names, \, verbose=False, rename=False, module=None)*

typename:实际上就是你通过namedtuple创建的一个元组的子类的类名,通过这样的方式我们可以初始化各种各样的实例化元组对象。

field_names:类似于字典的key,在这里定义的元组可以通过这样的key去获取里面对应索引位置的元素值,这样的key可以是列表,也可以是用空格、/和逗号这样的分隔符隔开的字符串。

1
2
3
4
5
6
7
8
9
from collections import namedtuple

Point = namedtuple("Point",["x","y"])

p1 = Point(x=1,y=2)
print(p1.x) #1
p2 = Point(x=1,y=2)
print(p1==p2) #true
#需要注意的是,因为元组的不可修改性,所以一旦实例化赋值以后,就不能再修改了

学生系统

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
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
data = [
{
'id': 10195501423,
'name':'Jason',
'sex':'Male',
'address': '浙江'
},
{
'id': 10195501424,
'name': 'keke',
'sex': 'Male',
'address': '上海'
},
{
'id': 10195501425,
'name': 'feifei',
'sex': 'Male',
'address': '上海'
},
{
'id': 10195501426,
'name': '弘弘',
'sex': 'Male',
'address': '浙江'
}
]
# 美化显示
def beautify_print (data_list):
for index,student in enumerate(data_list):
print(f'序号:{index+1}',end='\t')
print(f'ID:{student["id"]}',end='\t')
print(f'姓名:{student["name"]}',end='\t')
print(f'性别:{student["sex"]}',end='\t')
print(f'地址:{student["address"]}')
# 控制输入
def input_name():
while True:
name = input('输入学生姓名:').strip()
if name:
return name
else:
continue

# 选择性别
def choose_sex():
while True:
print('1.(Male)||2.(Female)')
n = input('Choose The Gender')
if n=='1':
return 'Male'
elif n=='2':
return 'Female'
else:
continue


# 1. 显示所有学生信息
def show_all():
beautify_print(data)
# 2. 新建所有学生信息

def create_student():
id = input('输入学生id:')
name = input_name()
sex = choose_sex()
address = input('输入学生地址:')
student = {
'id' : id,
'name' : name,
'sex':sex,
'address':address
}
data.append(student)
# 3. 查询所有学生信息

def find_student():
name = input('查询学生的姓名:')
for student in data:
if student['name'] == name:
print(f'查到学生{name}{student}')
return
else :
print('查无此人')
# 4. 修改学生信息

def modify_student():
name = input('查询学生的姓名:')
for student in data:
if student['name'] == name:
print(f'查到学生{name}{student}')
student['id'] = input('输入id:')
student['name'] = input('输入名字:')
student['sex'] = input('输入性别:')
student['address'] = input('输入性别:')
else:
print('查无此人')
# 5. 删除 学生信息

def remove_student():
name = input('要删除的学生的姓名:')
for student in data:
if student['name'] == name:
print(student)
data.remove(student)
print('已经被删除了')
else:
print('查无此人')
while True:
print('''
*************************
1. 显示所有学生信息
2. 新建学生信息
3. 查询学生信息
4. 修改学生信息
5. 删除学生信息
0,退出系统
*************************
''')
op = input('请输入序号:')# input输入的都是字符串
if op == '1':
show_all()
elif op == '2':
create_student()
elif op == '3':
find_student()
elif op == '4':
modify_student()
elif op == '5':
remove_student()
else:
break
-------------本文结束,感谢您的阅读-------------