返回顶部
首页 > 资讯 > 后端开发 > Python >Pyhton-类(2)
  • 392
分享到

Pyhton-类(2)

Pyhton 2023-01-30 23:01:08 392人浏览 泡泡鱼

Python 官方文档:入门教程 => 点击学习

摘要

    @ 继承(inheritance) 什么是继承: B继承A:A是父类(超类),B是子类(基类)。继承可以实现代码重复利用,实现属性和方法继承。 继承可以使子类拥有父类的属性和方法,也可以重新定义某些属性、重写某些方法,即覆盖

 

 

@ 继承(inheritance)


什么是继承:

B继承A:A是父类(超类),B是子类(基类)。继承可以实现代码重复利用,实现属性和方法继承。

继承可以使子类拥有父类的属性和方法,也可以重新定义某些属性、重写某些方法,即覆盖父类原有的属性和方法,使其获得父类不同的功能。当然,也可以在子类中新设置属性和方法。从技术上看,OOP里继承最主要的用途是实现多态,对于多态而言,最重要的是接口的继承性(属性和方法是否存在继承性),这是不一定的。继承也不是全为了代码的重复利用,而是为了理顺关系。

对于 python 中的继承,前面一直在使用,那就是我们写的类都是新式类,所有新式类都是继承自 object 类。不要忘记,新式类的一种写法:

class NewStyle(object):
    pass

这就是典型的继承。

继承的基本概念:

class Person:
    def __init__(self,name):
        self.name = name
        
    def get_name(self):
        print ("hello,{}!".fORMat(self.name))

    def setHeight(self, n):
        self.length = n

    def breast(self, n):
        print ("My breast is: ",n)

class Boy(Person):
    def setHeight(self):
        print ("The height is:1.80m .")


j = Boy('jimmy')
j.get_name()
j.setHeight()
j.breast(90)
打印结果:
hello,jimmy!
The height is:1.80m .
My breast is:  90

首先,定义了一个父类 Person,定义一个子类 Boy,Boy类的括号中是Person,这就意味着 Boy 继承了 Person,Boy 是 Person 的子类,Person 是 Boy 的父类。那么 Boy 就全部拥有了 Person 中的方法和属性。

如果 Boy 里面有一个和 Person 同样名称的方法,那么就把 Person 中的同一个方法遮盖住了,显示的是 Boy 中的方法,这叫做方法的重写。实例化类 Boy之后,执行实例方法  j.setHeight(),由于在类 Boy中重写了 setHeight 方法,那么 Person 中的那个方法就不显作用了,在这个实例方法中执行的是类 Boy 中的方法。

虽然在类 Boy 中没有看到 get_name() 方法,但是因为它继承了 Person,所以 j.get_name() 就执行类 Person 中的方法。同理  j.breast(90) ,它们就好像是在类 Boy 里面已经写了这两个方法一样。既然继承了,就可以使用。

多重继承:

子类继承多个父类:

 

class Person:
    def eye(self):
        print("two eyss")
    def breast(self,n):
        print("the breast is:",n)
class Girl:
    age = 18
    def color(self):
        print("the girl is white.")
class HotGirl(Person,Girl):
    pass

 

在类的名字后面的括号中把所继承的两个类的名字写上,HotGirl 就继承了Person 和 Girl这两个类。实例化类 HotGirl,既然继承了上面的两个类,那么那两个类的方法就都能够拿过来使用。在类 Girl 中, age = 28,在对 HotGirl 实例化之后,因为继承的原因,这个类属性也被继承到 HotGirl 中,因此通过实例得到它。

继承的特点,即将父类的方法和属性全部承接到子类中;如果子类重写了父类的方法,就使用子类的该方法,父类的被遮盖。

 多重继承的顺序:

如果一个子类继承了两个父类,并且两个父类有同样的方法或者属性,那么在实例化子类后,调用那个方法或属性,是属于哪个父类的呢?造一个没有实际意义,纯粹为了解决这个问题的程序:

class K1(object):
    def foo(self):
        print("K1-foo")
class K2(object):
    def foo(self):
        print("K2-foo")
    def bar(self):
        print("K2-bar")
class J1(K1, K2):
    pass
class J2(K1, K2):
    def bar(self):
        print("J2-bar")
class C(J1, J2):
    pass

print(C.__mro__)
m = C()
m.foo()
m.bar()
打印结果:
(<class '__main__.C'>, <class '__main__.J1'>, <class '__main__.J2'>, <class '__main__.K1'>, <class '__main__.K2'>, <class 'object'>)
K1-foo
J2-bar

print C.__mro__打印出类的继承顺序。

从上面清晰看出来了,如果要执行 foo() 方法,首先看 J1,没有,看 J2,还没有,看 J1 里面的 K1,有了,即 C(没有)==>J1(没有)==>J2(没有)==>K1(找到了);bar() 也是按照这个顺序,在 J2 中就找到了一个。

这种对继承属性和方法搜索的顺序称之为“广度优先”。新式类用以及 python3.x 中都是按照此顺序原则搜寻属性和方法的。

但是,在旧式类中,是按照“深度优先”的顺序的。因为后面读者也基本不用旧式类,所以不举例。

 

@ super函数


 对于初始化函数的继承,跟一般方法的继承不同:

class Person:
    def __init__(self):
        self.height = 160
    def about(self, name):
        print("{} is about {}".format(name, self.height))
class Girl(Person):
    def __init__(self):
        self.breast = 90
    def about(self, name):
        print("{} is a hot girl, she is about {}, and her breast is {}".format(name, self.height, self.breast))

cang = Girl()
cang.about("wangguniang")
打印结果:
Traceback (most recent call last):
  File "test1.py", line 14, in <module>
    cang.about("wangguniang")
  File "test1.py", line 11, in about
    print("{} is a hot girl, she is about {}, and her breast is {}".format(name, self.height, self.breast))
AttributeError: 'Girl' object has no attribute 'height'

在上面这段程序中,类 Girl 继承了类 Person。在类 Girl 中,初始化设置了 self.breast = 90,由于继承了 Person,按照前面的经验,Person 的初始化函数中的 self.height = 160 也应该被 Girl 所继承过来。然后在重写的 about 方法中,就是用 self.height。

实例化类 Girl,并执行 cang.about("wangguniang"),试图打印出一句话 wangguniang is a hot girl, she is about 160, and her bereast is 90。保存程序,运行报错!

信息显示 self.height 是不存在的。也就是说类 Girl 没有从 Person 中继承过来这个属性。

在 Girl中发现, about 方法重写了,__init__方法,也被重写了。它跟类 Person 中的__init__重名了,也同样是重写了那个初始化函数。这是因为在子类中重写了某个方法之后,父类中同样的方法被遮盖了。

使用super 函数:

class Person:
    def __init__(self):
        self.height = 160
    def about(self, name):
        print("{} is about {}".format(name, self.height))
class Girl(Person):
    def __init__(self):
        super().__init__()
        self.breast = 90
    def about(self, name):
        print("{} is a hot girl, she is about {}, and her breast is {}".format(name, self.height, self.breast))

cang = Girl()
cang.about("wangguniang")
打印结果:
wangguniang is a hot girl, she is about 160, and her breast is 90

在子类中,__init__方法重写了,为了调用父类同方法,使用 super(Girl, self).__init__()的方式。super 函数的参数,第一个是当前子类的类名字,第二个是 self,然后是点号,点号后面是所要调用的父类的方法。同样在子类重写的 about 方法中,也可以调用父类的 about 方法。

最后要提醒注意:super 函数仅仅适用于新式类。

 

@ 绑定方法与非绑定方法


要通过实例来调用类的方法(函数),经常要将类实例化。方法是类内部定义函数,只不过这个函数的第一个参数是 self。(可以认为方法是类属性,但不是实例属性)。必须将类实例化之后,才能通过实例调用该类的方法。调用的时候在方法后面要跟括号(括号中默认有 self 参数,可以不写出来)。通过实例调用方法,称这个方法绑定在实例上。

 调用绑定方法:
class Person(object):
    def foo(self):
        pass
pp = Person()    #实例化
print(pp.foo())  #调用方法

这样就实现了方法和实例的绑定,于是通过 pp.foo() 即可调用该方法。

调用非绑定方法:

class Person:
    def __init__(self):
        self.height = 160
    def about(self, name):
        print("{} is about {}".format(name, self.height))
class Girl(Person):
    def __init__(self):
        super().__init__()
        self.breast = 90
    def about(self, name):
        print("{} is a hot girl, she is about {}, and her breast is {}".format(name, self.height, self.breast))

cang = Girl()
cang.about("wangguniang")
打印结果:
wangguniang is a hot girl, she is about 160, and her breast is 90

在子类 Girl 中,因为重写了父类的__init__方法,如果要调用父类该方法,在上节中不得不使用 super().__init__()调用父类中因为子类方法重写而被遮蔽的同名方法。

其实,非绑定方法,因为在子类中,没有建立父类的实例,却要是用父类的方法。对于这种非绑定方法的调用,还有一种方式。不过这种方式现在已经较少是用了,因为有了 super 函数。为了方便读者看其它有关代码,还是要简要说明。

例如在上面代码中,在类 Girl 中想调用父类 Person 的初始化函数,则需要在子类中,写上这么一行:Person.__init__(self)

这不是通过实例调用的,而是通过类 Person 实现了对__init__(self)的调用。这就是调用非绑定方法的用途。但是,这种方法已经被 super 函数取代,所以,如果在编程中遇到类似情况,推荐使用 super 函数。

 

@ 静态方法和类方法


已知,类的方法第一个参数必须是 self,并且如果要调用类的方法,必须将通过类的实例,即方法绑定实例后才能由实例调用。如果不绑定,一般在继承关系的类之间,可以用 super 函数等方法调用。

这里再介绍一种方法,这种方法的调用方式跟上述的都不同,这就是:静态方法类方法

class StaticMethod:
    @staticmethod
    def foo():
        print("This is static method foo().")

class ClaSSMethod:
    @classmethod
    def bar(cls):              #类方法中要有cls参数
        print("This is class method bar().")
        print("bar() is part of class:", cls.__name__)

static_foo = StaticMethod()    #实例化
static_foo.foo()               #实例调用静态方法
StaticMethod.foo()             #通过类来调用静态方法
print("********")
class_bar = ClassMethod()
class_bar.bar()
ClassMethod.bar()
打印结果:
This is static method foo().
This is static method foo().
********
This is class method bar().
bar() is part of class: ClassMethod
This is class method bar().
bar() is part of class: ClassMethod

Python 中:

@staticmethod表示静态方法

@classmethod表示类方法

先看静态方法,虽然名为静态方法,但也是方法,所以,依然用 def 语句来定义。需要注意的是文件名后面的括号内,没有self,这和前面定义的类中的方法是不同的,也正是因着这个不同,才给它另外取了一个名字叫做静态方法。如果没有 self,那么也就无法访问实例变量、类和实例的属性了,因为它们都是借助 self 来传递数据的。

在看类方法,同样也具有一般方法的特点,区别也在参数上。类方法的参数也没有 self,但是必须有 cls 这个参数。在类方法中,能够访问类属性,但是不能访问实例属性。

简要明确两种方法。下面看调用方法。两种方法都可以通过实例调用,即绑定实例。也可以通过类来调用,即 StaticMethod.foo() 这样的形式,这也是区别一般方法的地方,一般方法必须用通过绑定实例调用。

 

end~
 
****** 几米花的Python ****** 博客主页:https://www.cnblogs.com/jimmy-share/  欢迎转载 ~

--结束END--

本文标题: Pyhton-类(2)

本文链接: https://lsjlt.com/news/180703.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

猜你喜欢
  • Pyhton-类(2)
        @ 继承(inheritance) 什么是继承: B继承A:A是父类(超类),B是子类(基类)。继承可以实现代码重复利用,实现属性和方法继承。 继承可以使子类拥有父类的属性和方法,也可以重新定义某些属性、重写某些方法,即覆盖...
    99+
    2023-01-30
    Pyhton
  • pyhton习题20190201
    #20190131'''检查ipV4的有效性,有效则返回True,否则返回False,(提示使用split函数进行分割)'''import osdef print_ping_ip(ip): s = os.system('ping '+ip...
    99+
    2023-01-30
    习题 pyhton
  • 类与对象2
    1. 重写类方法 第一步:在类的外部写一个函数; 第二步:把这个新函数的名字赋值给类.原始函数 (注意:这里的赋值是在替换方法,并不是调用函数,所以【不要加上括号】—— 写成类.原始函数() = 新函数()是错误的。) 语法格式如下: ...
    99+
    2023-01-31
    对象
  • leetcode 2525 根据规则将箱子分类 c++ pyhton java c题解
    leetcode 2525 根据规则将箱子分类 题目 给你四个整数 length ,width ,height 和 mass ,分别表示一个箱子的三个维度和质量,请你返回一个表示箱子 类别 的字符串。...
    99+
    2023-10-24
    leetcode c++ java
  • 2.Python3 数据类型
    一、数据类型初识 1、数字2 是一个整数的例子。长整数 不过是大一些的整数。3.23和52.3E-4是浮点数的例子。E标记表示10的幂。在这里,52.3E-4表示52.3 * 10-4。(-5+4j)和(2.3-4.6j)是复数的例子,其中...
    99+
    2023-01-31
    数据类型
  • Python学习—pyhton中的进程
    1.进程定义 进程: 进程就是一个程序在一个数据集上的一次动态执行过程。进程一般由程序、数据、进程控制块(pcb)三部分组成。(1)我们编写的程序用来描述进程要完成哪些功能以及如何完成;(2)数据则是程序在执行过程中所需要使用的资源;(3)...
    99+
    2023-01-31
    进程 Python pyhton
  • python 继承2个父类
    #!/usr/bin/env pythonclass father(object): def __init__(self,tail,heav): self.tail=tail self.heav=heavclass mother(obje...
    99+
    2023-01-31
    python 个父类
  • MySQL数据类型 - JSON数据类型 (2)
    JSON值的规范化、合并和自动包装 当一个字符串被解析并发现是一个有效的JSON文档时,它也会被规范化。这意味着,具有与稍后在文档中找到的键(从左到右)重复的键的成员将被丢弃。JSON_OBJECT()调用生成的对象值只包含第二个key1元...
    99+
    2019-09-03
    MySQL数据类型 - JSON数据类型 (2) 数据库入门 数据库基础教程 数据库 mysql
  • Java的整型类型中如何实现2+2=5
    Java的整型类型中如何实现2+2=5,相信很多没有经验的人对此束手无策,为此本文总结了问题出现的原因和解决方法,通过这篇文章希望你能解决这个问题。先看下这段神奇的Java代码:public static void&nb...
    99+
    2023-06-02
  • Redis入门(2) - 数据类型
    Redis中的数据类型 字符串 散列 列表 集合 有序集合 Redis中的数据类型 Redis定义了这几种数据类型: string(字符串) hash(散列) list(列表) set(集合) zset(有序集合) 后面会介...
    99+
    2017-07-10
    Redis入门(2) - 数据类型
  • Java类与对象详解(2)
      this引用 为什么要有this引用 先来看一个日期类的例子: ​public class Date { public int year; public int month; public int day; /...
    99+
    2023-09-01
    java 开发语言
  • Pyhton模块和包相关知识总结
    目录一、模块二、模块的搜索顺序三、使模块下方的测试代码在导入时不会执行四、包五、发布模块六、安装模块七、卸载模块八、pip 安装第三方模块一、模块 每一个以扩展名 py 结尾额 Py...
    99+
    2024-04-02
  • pyhton数据挖掘self原理是什么
    本篇内容主要讲解“pyhton数据挖掘self原理是什么”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“pyhton数据挖掘self原理是什么”吧!1. 什么是class,什么是instance,...
    99+
    2023-06-25
  • python装饰器2:类装饰器
    装饰器1:函数装饰器 装饰器2:类装饰器 装饰器3:进阶 本文是装饰器相关内容的第二篇,关于类装饰器。 "类装饰器"有两种解读方式:用来装饰类的装饰器;类作为装饰器装饰其它东西。你如何认为取决于你,两种说法都有出现在其它的文章中。我的...
    99+
    2023-01-30
    python
  • day 4 - 2 数据类型练习
    1. 在字符串中数字相连的为一组,输出数字共有几组 如: 123sdf456sdf789  数字为:3组 info = input(">>>") for i in info: if i.isalpha(): ...
    99+
    2023-01-30
    数据类型 day
  • day 3 - 2 数据类型练习
    1.有变量 name = " aleX leNB " 完成如下操作 name = " aleX leNB " # 1) 移除两端空格n1 = name.strip()print(n1)   # 2) 移除左边的 aln2 = name[3...
    99+
    2023-01-30
    数据类型 day
  • 详解C++之类和对象(2)
    目录一.构造函数1.构造函数的定义:2.构造函数的特征:3.构造函数的实现:3.1.系统默认的构造函数3.2无参构造3.3 带参构造二 析构函数1.析构函数的定义2.析构函数的特征三...
    99+
    2024-04-02
  • Pyhton自动化测试持续集成和Jenkins
    持续集成 官方术语: 持续集成(Continuous Integration),也就是我们经常说的 CI持续集成(CI)是一种实践,可以让团队在持续的基础上收到反馈并进行改进,不必等...
    99+
    2024-04-02
  • php数组分为哪2种类型
    PHP是一种非常流行的编程语言,被广泛用于Web开发。在PHP中,数组是一个极其重要的数据类型,广泛运用于代码中。PHP中的数组有两种类型,分别是索引数组和关联数组。索引数组在PHP中,索引数组最为常见。它是一种用数字来索引元素的数组。可以...
    99+
    2023-05-22
  • Pyhton爬虫知识之正则表达式详解
    目录前言1、正则表达式基础2、正则表达式的基本符号2.1 点号 “.”2.2 星号 “*”2.3 问号 “”2...
    99+
    2024-04-02
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作