文章目录

  • ​​1 函数​​
  • ​​1.1 默认参数​​
  • ​​1.2 函数返回多值​​
  • ​​1.3 函数return​​
  • ​​1.4 定义可变参数​​
  • ​​1.5 递归函数​​
  • ​​2 类的继承​​
  • ​​2.1 多态​​
  • ​​2.2 多重继承​​
  • ​​2.3 继承​​
  • ​​2.4 判断类型​​
  • ​​2.5 获取对象信息​​

1 函数

1.1 默认参数

函数的默认参数的作用是简化调用,只需把必须的参数传进去。在需要的时候,又可传入额外的参数来覆盖默认参数值。由于函数的参数按从左到右的顺序匹配,所以默认参数只能定义在必需参数的后面。下面的代码是一个例子:

def power(x, n = 2): # 定义一个幂函数,默认为求二次方
s = 1
while n > 0:
n = n -1
s = s * x
return s

输入:

power(9)

输出如下:

81

输入如下:

power(2,5)

输入如下:

32

1.2 函数返回多值

函数可以返回多个值。

import math
def move(x, y, step, angle):
nx = x + step * math.cos(angle)
ny = y + step * math.sin(angle)
return nx, ny

这样就可以同时获得返回值:

x, y = move(100, 100, 60, math.pi / 6)
print(x, y)

输出如下:

151.96152422706632 130.0

但是其实Python函数返回的仍然是单一值:

r = move(100, 100, 60, math.pi / 6)
print(r)

输出如下:

(151.96152422706632, 130.0)

上述代码表明,其实函数返回的是一个tuple。返回一个tuple可以省略括号,而多个变量可以同时接收一个tuple,按位置赋给对应的值,所以,Python的函数返回多值其实就是返回一个tuple,但写起来更方便。

1.3 函数return

在Python中,定义一个函数要使用 def 语句,依次写出函数名、括号、括号中的参数和冒号​​:​​​,然后,在缩进块中编写函数体,函数的返回值用​​return​​​语句返回。函数体内部的语句在执行时,一旦执行到​​return​​​时,函数就执行完毕,并将结果返回。如果没有​​return​​​语句,函数执行完毕后也会返回结果,只是结果为​​None​​​。​​return None​​​可以简写为​​return​​。

1.4 定义可变参数

想让函数接受任意个参数,可以定义一个可变参数

def fn(*args):
print(args)

可变参数的名字前有个​​*​​号,可传入0个、1个或多个参数给可变参数:

输入如下:

fn()

输出如下:

()

输入如下:

fn('a')

输出如下:

('a',)

输入如下:

fn('a', 'b', 'c')

输出如下:

('a', 'b', 'c')

Python会把传入的参数组装成一个​​tuple​​​传递给可变参数,因此,在函数内部,直接把变量 ​​args​​​看成一个 ​​tuple​​就好了。定义可变参数的目的是为了简化调用。

1.5 递归函数

如果一个函数在内部调用自身本身,这个函数就是递归函数。递归函数的优点是定义简单,逻辑清晰。函数调用是通过栈——​​stack​​这种数据结构实现的,每当进入一个函数调用,栈就会加一层栈帧;每当函数返回,栈就会减一层栈帧。


2 类的继承

2.1 多态

类具有继承关系,子类可以看做父类的类型。如果从​​Person​​​派生出 ​​Student​​​和​​Teacher​​​,并都写了一个 ​​whoAmI()​​方法:

class Person(object):
def __init__(self, name, gender):
self.name = name
self.gender = gender
def whoAmI(self):
return 'I \'m a person, my name is %s'% self.name

再输入:

class Student(Person):
def __init__(self, name, gender, score):
super(Student, self).__init__(name, gender)
self.score = score
def whoAmI(self):
return 'I \'m a student, my name is %s'% self.name

再输入:

class Teacher(Person):
def __init__(self, name, gender, course):
super(Teacher, self).__init__(name, gender)
self.course = course
def whoAmI(self):
return 'I \'m a teacher, my name is %s'% self.name

在一个函数中,如果接收一个变量​​x​​​,则无论 ​​x​​​是 ​​Person​​​、​​Student​​​还是 ​​Teacher​​,都可以正确打印出结果:

def who_am_i(x):
print(x.whoAmI())

再输入:

p = Person('Tim', 'Male')
s = Student('Bob', 'Male', 88)
t = Teacher('Alice', 'Female', 'English')

再输入:

who_am_i(p)
who_am_i(s)
who_am_i(t)

输出如下:

I 'm a person, my name is Tim
I 'm a student, my name is Bob
I 'm a teacher, my name is Alice

这种行为称为多态。也就是说,方法调用将作用在​​x​​​ 的实际类型上。​​s​​​是​​Student​​类型,它实际上拥有自己的 whoAmI()方法以及从 Person继承的 whoAmI方法,但调用 s.whoAmI()总是先查找它自身的定义,如果没有定义,则顺着继承链向上查找,直到在某个父类中找到为止。

2.2 多重继承

除了从一个父类继承外,Python允许从多个父类继承,称为多重继承。

class A(object):
def __init__(self, a):
print('init A...')
self.a = a

再输入:

class B(A):
def __init__(self, a):
super(B, self).__init__(a)
print('init B...')

再输入:

class C(A):
def __init__(self, a):
super(C, self).__init__(a)
print('init C...')

再输入:

class D(B, C):
def __init__(self, a):
super(D, self).__init__(a)
print('init D ...')

【Python知识点】-函数/类的继承_Python


D 同时继承自 B 和 C,也就是 D 拥有了 A、B、C 的全部功能。多重继承通过​​super()​​​调用​​__init__()​​​方法时,A 虽然被继承了两次,但​​__init__()​​只调用一次。多重继承的目的是从两种继承树中分别选择并继承出子类,以便组合功能使用。

2.3 继承

如果已经定义了Person类,需要定义新的Student和Teacher类时,可以直接从Person类继承:

class Person(object):
def __init__(self, name, gender):
self.name = name
self.gender = gender

定义Student类时,只需要把额外的属性加上,例如score:

class Student(Person):
def __init__(self, name, gender, score):
super(Student, self).__init__(name, gender)
self.score = score

一定要用 ​​super(Student, self).__init__(name, gender)​​​ 去初始化父类,否则,继承自 Person 的 Student 将没有 name 和 gender。函数​​super(Student, self)​​​将返回当前类继承的父类,即 Person ,然后调用​​__init__()​​​方法,注意​​self​​​参数已在​​super()​​​中传入,在​​__init__()​​中将隐式传递,不需要写出(也不能写)。

2.4 判断类型

​isinstance()​​可以判断一个变量的类型。既可以用在Python内置的数据类型如str、list、dict,也可以用在自定义的类,本质上都是数据类型。假设有如下的 Person、Student 和 Teacher 的定义及继承关系如下:

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

class Teacher(Person):
def __init__(self, name, gender, course):
super(Teacher, self).__init__(name, gender)
self.course = course

再输入:

p = Person('Tim', 'Male')
s = Student('Bob', 'Male', 88)
t = Teacher('Alice', 'Female', 'English')

下面的代码使用​​isinstance()​​​判断​​p​​​、​​s​​​、​​t​​的类型:

输入:

isinstance(p, Person)
isinstance(p, Student)
isinstance(p, Teacher)

输出如下:

True
False
False

上述代码说明:在继承链上,一个父类的实例不能是子类类型,因为子类比父类多了一些属性和方法。一个实例可以看成它本身的类型,也可以看成它父类的类型。

2.5 获取对象信息

输入如下:

type(s)

输出如下:

<class '__main__.Student'>

可以用 ​​dir()​​ 函数获取变量的所有属性:

dir(123) # 整数也拥有很多属性

输出如下:

['__abs__', '__add__', '__and__', '__bool__', '__ceil__', '__class__', '__delattr__', '__dir__', '__divmod__', '__doc__', '__eq__', '__float__', '__floor__', '__floordiv__', '__format__', '__ge__', '__getattribute__', '__getnewargs__', '__gt__', '__hash__', '__index__', '__init__', '__init_subclass__', '__int__', '__invert__', '__le__', '__lshift__', '__lt__', '__mod__', '__mul__', '__ne__', '__neg__', '__new__', '__or__', '__pos__', '__pow__', '__radd__', '__rand__', '__rdivmod__', '__reduce__', '__reduce_ex__', '__repr__', '__rfloordiv__', '__rlshift__', '__rmod__', '__rmul__', '__ror__', '__round__', '__rpow__', '__rrshift__', '__rshift__', '__rsub__', '__rtruediv__', '__rxor__', '__setattr__', '__sizeof__', '__str__', '__sub__', '__subclasshook__', '__truediv__', '__trunc__', '__xor__', 'bit_length', 'conjugate', 'denominator', 'from_bytes', 'imag', 'numerator', 'real', 'to_bytes']

​dir()​​​返回的属性是字符串列表。如果已知一个属性名称,要获取或者设置对象的属性,就需要用 ​​getattr()​​​和 ​​setattr( )​​函数了:

getattr(s, 'name')

输出如下:

'Bob'

再输入:

setattr(s, 'name', 'XvSong')
s.name

输出如下:

'XvSong'

输入如下:

getattr(s, 'age', 20) # 获取age属性,如果属性不存在,就返回默认值20

输出如下:

20

下面的代码是一个例子:

对于Person类的定义:

class Person(object):
def __init__(self, name, gender):
self.name = name
self.gender = gender

希望除了​​name​​​和​​gender​​​外,可以提供任意额外的关键字参数,并绑定到实例,请修改​​Person​​​的 ​​__init__()​​定 义,完成该功能。

下面的代码是解析:

class Person(object):
def __init__(self, name, gender, **kw):
self.name = name
self.name = gender
for k ,v in kw.items():
setattr(self, k, v)

再输入:

p =Person('Bob', 'Male', age = 10, course = 'Python')

print(p.age)
print(p.course)

输出如下:

10
Python