菜鸡自学 Python 笔记(三)
九.函数
函数是什么?
函数是组织好的,可重复使用的,用来实现单一,或相关联功能的代码段。
函数又有什么用呢?
函数能提高应用的模块性,和代码的重复利用率。
简单了解了函数,那我们就来看看Python 中的几种函数吧!
1.内置函数
内置函数 | 作用 | 例子 |
---|---|---|
abs(x) | 返回数值x的绝对值。如果x是复数,则返回该值。 | print(abs(-3.14)) # 3.14 print(abs(1+2j)) #2.23606797749979 |
chr(i) | i是ASCII字符码 0~ 255,函数返回数值i的单字符字符串。 | print(chr(97)) # 'a' |
ord() | 与chr()相反 | print(ord('a')) # 97 |
complex(real[,imag]) | 创建一个复数 | print(complex(1,2)) #(1+2j) |
dir([object]) | 不带参数时,返回当前范围内的变量、方法和定义的类型列表;带参数时,返回参数的属性、方法列表。 | import sys print(dir(sys)) print(dir()) |
divmod(a,b) | 以元组的形式返回a除以b的商与余数 | print(divmod(8,2)) # (4,0) |
eval(expression[, globals[, locals]]) | 执行一个字符串表达式,并返回表达式的值。 | print('3*4') # 3*4 print(eval('3*4')) # 12 |
float(x) | 将x转化为浮点型 | print(float('10')) # 10.0 |
pow(x,y[,z]) | 返回 x 的 y 次方 的值。如果 z 在存在,返回 pow(x,y) %z。 | print(pow(2,2)) #4 print(pow(2,2,3)) #1 |
tuple(sequence) | 创建一个元组对象 | print(tuple([1,2,3])) # (1,2,3) print(tuple('Asu')) # ('A', 's', 'u') |
2.自定义函数
除了系统内置的函数,我们也可以自己动手定义自己需要的函数。
格式:
def 函数名(参数列表):
函数体
举例:
# 自定义函数
def say_hi():
print('Hi there!')
print('Wish to you!') # 在我们定义函数时,结尾要留有两个空行
print("Start")
say_hi() # 先定义后使用
print("Finish")
3.带参数的函数
在使用函数时,我们具有形参和实参的概念。
形参:形式上的参数,就像在定义函数时括号里的参数。它代表参数,但不知道具体的值。
实参:调用函数时的参数,具体的参数。
例如,以下,我们在say_hi()函数中传入一个“name”参数:
def say_hi(name):
print(f'Hi {name}!')
print('Wish to you!')
say_hi("Asu")
say_hi("Dodo")
- 这里我们需要注意传参时的位置参数和关键字参数
位置参数:依照参数的排列顺序,绝对其对应的值
关键字参数:直接设置参数的名称和值,可以不依照顺序
def say_hi(name1, name2):
print(f'Hi {name1}! Hi {name2}!')
say_hi("Asu", "Dodo")
say_hi(name2='Asu', name1='Dodo')
4.函数的返回值
return语句代表函数的退出,并向调用方返回一个或多个值或一个表达式。
def square(number):
return number * number
print(square(4))
# 16
返回多个值:
def num(x,y):
return x,y
print(num(4,8))
# (4,8) 以元组的形式返回
如果函数没有返回值,则会返回 None。
十.处理异常和错误
对于我们这样的初学者,红色报错,我们会经常遇到。虽然bug很讨厌,但是我们也要学会去处理解决这些讨厌的家伙。
我们常见的有语法错误(如,少写了:,搞错了缩进等的)和异常(如,除以零等等)。
1.异常捕捉
下面我们可以用try /except语句来处理这些异常。
- 这样当用户输入一个错误的值时,系统不会直接崩溃报错,而是输出你想输出的提示。
格式:
try:
执行语句
except 异常类型:
异常时执行语句
try 语句按照如下方式工作;
- 首先,执行 try 子句(在关键字 try 和关键字 except 之间的语句)。
- 如果没有异常发生,忽略 except 子句,try 子句执行后结束。
- 如果在执行 try 子句的过程中发生了异常,那么 try 子句余下的部分将被忽略。如果异常的类型和 except 之后的名称相符,那么对应的 except 子句将被执行。
- 如果一个异常没有与任何的 except 匹配,那么这个异常将会传递给上层的 try 中。
例如:
try:
age = int(input('Age: '))
income = 20000
risk = income/age
print(age)
except ValueError: # 类型错误
print('Invalid value')
except ZeroDivisionError: # 除法错误
print('Age cannot be 0')
除了try /except语句,我们还可以用try/except…else语句
try:
执行语句
except 异常类型:
异常时执行语句
else:
没有异常时执行语句
try-finally 语句(也常用来清除异常)
try:
执行语句
except 异常类型:
异常时执行语句
else:
没有异常时执行语句
finally:
不管有没有异常都会执行的语句
2.抛出异常
raise语句 抛出一个指定的异常。
格式:raise [Exception [, args [, traceback]]]
raise 唯一的一个参数指定了要被抛出的异常。它必须是一个异常的实例或者是异常的类(也就是 Exception 的子类)。
如果你只想知道这是否抛出了一个异常,并不想去处理它,那么 raise 语句是最佳的选择。
x = 10
if x > 5:
raise Exception(f'x 不能大于 5。x 的值为: {x}')
3.自定义异常
内置异常通常是定义在exceotions 模块中,解释器启动时,该模块就会加载。而自定义异常,必须继承内置异常,或者说由内置异常派生而来。
class NameError(Exception): # 定义异常
pass # 继承
try :
raise NameError() # 抛出异常
except NameError: # 捕捉异常
print("Name!")
# Name!
十一.类与对象
对象是类的实例化。对象 = 属性+方法。
而我们又把具有相同属性及相同行为的一组对象称为类。
1.创建类和实例对象
如下,我们用关键字class来创建一个简单的类:
class Cat:# 类名以大写字母开头
# 属性
name = "Dodo"
age = 2
weight = 5
is_lazy = True
# 方法
def talk(self):
print(f"miao~ I am {self.name}.")
cat1 = Cat() # 创建实例对象
cat1.talk() # 调用类中的方法
- 这里的self 用于在对象内指向对象本身。Python中的self其实跟C++的this一样,都是代表对象本身。
- 而这里我们访问对象的某个属性时,可以用object.attribute的格式,即对象.属性。
2.属性的公有、私有
一般的属性默认为公有,而将其变为私有也很简单,就是在属性名前加下划线。
私有则意味着不能进行外部访问,但是如果一定要去访问它,也不是没有办法。我们可以定义一个内部函数,对其进行内部访问。
# 私有,公有
class Cat:
name = "Dodo" # 公有
__age =2 # 私有 在变量名前加下划线
def get_age(self):
return self.__age
cat1 = Cat()
print(cat1.name) # 公有可以访问
# print(cat1.__age) # 私有不能外部访问 ,会报错!
print(cat1.get_age()) # 利用一个方法内部访问
3.魔法方法
首先,先介绍一个特殊的方法,构造方法 __ init __ (self),即在创建对象时自动调用的一个函数。
# 魔法方法
class Cat:
def __init__(self,name): # 构造函数,在创建实例的同时自动调用该函数
self.name = name
def talk(self):
print(f"miao~ I am {self.name}.")
cat1 = Cat("Dodo") # 传参
cat1.talk()
# miao~ I am Dodo.
除了这个,我们还有多种多样的魔法方法,如
__ del__ : 析构函数,释放对象时使用
__ repr__ : 打印,转换
__ setitem__ : 按照索引赋值
__ getitem__: 按照索引获取值
__ len__: 获得长度
__ cmp__: 比较运算
__ call__: 函数调用
__ add__: 加运算
__ sub__: 减运算
__ mul__: 乘运算
__ truediv__: 除运算
__ mod__: 求余运算
__ pow__: 乘方
等等。
详细可以看链接: Python中的魔术方法详解
介绍.
4.继承
面向对象程序主要有三个特性:
- 封装性:数据能通过一组接口函数来存取,经过封装的数据能够确保信息的隐秘性。
- 继承性:子类继承了其父类的成员变量与类方法。
- 多态性:多态允许一个函数有多种不同的接口。依照调用函数使用的参数,让类值得使用哪一种接口。
(1)继承
继承的新类又叫子类、派生类、衍生类,而旧类又称父类、基类、超类。
下面举个例子,就很容易理解:
class Dad:
def fun(self):
print("Dad's function")
class Kid(Dad): # class 子类(父类)
pass
d=Dad()
d.fun()
k=Kid() # 子类没有直接写出方法,但是在继承父类之后,也可以调用该方法。
k.fun()
这里需要注意,如果子类重写父类的方法或属性,就会把父类的方法覆盖。
class Dad:
def fun(self):
print("Dad's function")
class Kid(Dad):
def fun(self):
print("Kid's function")
d=Dad()
d.fun() # 父类并不会被覆盖
k=Kid()
k.fun()
(2)多重继承
子类不止可以继承一个父类,它可以进行多重继承:
class Base1:
def fool1(self):
print("Base1: fool1")
class Base2:
def fool2(self):
print("Base2: fool2")
class Base3:
def fool3(self):
print("Base3: fool3")
class C(Base1,Base2,Base3):
pass
c= C()
c.fool1()
c.fool2()
c.fool3()
(3)解决继承中的问题
在上面我们说过,如果子类重写父类的方法或属性,就会把父类的方法覆盖。如下例子,我们在写子类的构造函数时,会把继承的父类构造函数覆盖,导致子类无法访问到父类的is_happy属性。
# 如下报错
class Dad:
def __init__(self):
self.is_happy=True
def happy(self):
if self.is_happy:
print("what is a happy day!")
class Kid(Dad):
def __init__(self):
self.homework_finished=True
def homework(self):
if self.homework_finished:
print("Yeah!")
d=Dad()
d.happy()
k=Kid()
k.homework()
k.happy() # 报错
那我们要如何解决它呢?这里有两个方法。
# 1.调用未绑定的父类方法
class Dad:
def __init__(self):
self.is_happy=True
def happy(self):
if self.is_happy:
print("what is a happy day!")
class Kid(Dad):
def __init__(self):
Dad.__init__(self) # 这里self也是子类的实例对象
self.homework_finished=True
def homework(self):
if self.homework_finished:
print("Yeah!")
d=Dad()
d.happy()
k=Kid()
k.homework()
k.happy()
# 2.使用super函数
# 如果要修改父类,就只需要修改()里父类的名字就好,很方便
class Kid(Dad):
def __init__(self):
super().__init__()
self.homework_finished=True
def homework(self):
if self.homework_finished:
print("Yeah!")
(4)继承中一些相关函数
- issubclass(class, classinfo) 用于判断参数 class 是否是类型参数 classinfo 的子类。如果 class 是 classinfo 的子类返回 True,否则返回 False。
- isinstance(object, classinfo) 判断一个对象是否是一个已知的类型,类似 type()。如果对象的类型与参数二的类型(classinfo)相同则返回 True,否则返回 False。
# issubclass
class A:
pass
class B(A):
pass
class C:
pass
print(issubclass(B,A)) # True
print(issubclass(B,B)) # True
print(issubclass(C,A)) # False
# isinstance
a1=A()
print(isinstance(a1,A)) # True
print(isinstance(a1,B)) # False