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


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语句,函数执行完毕后也会返回结果,只是结果为Nonereturn 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派生出 StudentTeacher,并都写了一个 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,则无论 xPersonStudent还是 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 的实际类型上。sStudent类型,它实际上拥有自己的 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	...')

在这里插入图片描述
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()判断pst的类型:

输入:

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

希望除了namegender外,可以提供任意额外的关键字参数,并绑定到实例,请修改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
  • 3
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Python继承是面向对象编程的一种重要机制,它允许我们定义一个新,它继承了旧的所有属性和方法,并且可以在此基础上进行扩展和修改。下面是一些Python继承知识点: 1. 语法:定义一个继承自另一个的新时,需要在新名称后面加上父名称,并用圆括号括起来,如下所示: ```python class ChildClass(ParentClass): # 子的属性和方法定义 ``` 2. 继承型:Python支持单继承和多继承。单继承指子继承一个父,而多继承则允许子继承多个父。 3. 调用父方法:在子我们可以通过super()函数来调用父的方法,这样可以避免重复代码,同时也保证了子能够正确地继承的行为。 4. 方法重写:子可以重写父的方法,以实现自己的行为。当子定义了与父同名的方法时,它将覆盖父的方法。 5. 方法重载:Python不支持方法重载,即不能定义多个同名方法,只能通过默认参数或可变参数来实现似的效果。 6. 多态:Python的多态是基于继承和方法重写实现的。如果一个子重写了父的方法,那么在调用该方法时,如果对象是子的实例,那么将调用子的方法,否则将调用父的方法。 7. 抽象Python没有抽象的概念,但是可以通过abc模块来实现似的功能。抽象是一个不能被实例化的,它定义了一些方法,但是这些方法的实现是由其子来完成的。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值