• python(三) 函数_面向对象


    一、函数

    当我们发现有一些代码需要重复使用,你想怎么解决?

    函数:是组织好的,可重复使用的,用来实现单一,或相关联功能的代码块。 函数能提高应用的模块性,和代码的重复利用率。

    如我们前面使用的print() range()函数,但你也可以自己创建函数,这被叫做用户自定义函数。

    1.1 、函数的定义

    函数 用关键字 def修饰,后接函数标识符名称和圆括号() 和一个: 冒号
    函数内容: 要用一个tap 或四个空格缩进

    如:定义一个打印函数

    # 函数名 :我命名为了pr,函数内容里面只有一句打印语句
    
    def pr():
        print("你好,这是一个函数")
    
    # 函数定义完 不会自己执行,只有在调用的时候才会执行
    
    # 调用函数 如下:直接写函数名()
    pr()
    
    

    函数名命名规范:
      由字母、数字、下画线 _ 组成,其中数字不能打头,一般小写
      不能是 Python 关键字,但可以包含关键字
      不能包含空格

    1.2 、函数的参数

    函数是能够重复使用 而且不单单针对一个常量,所以我们可能处理很多未知数据,那这些未知的数据 我们又无法确定 那就可以用 参数,

    参数一般写在 函数的括号里面,然后在调用的时候传进行 最后在函数内容里使用
    函数在定义的时候 可以有参 或 无参

    有参 可以分为 :必传 ,可传

    def fun(a,b=0):
        pass
    

    我们可以看到上面这个函数 a参数是必传,也就是在调用fun这个函数的时候 必须传一个值给a,b是可传 可不传 当你不传的时候b就默认为0

    从调用看 参数分为:
    位置传参

    def fun01(a,b,c,d=1):
        print(a)
        print(b)
        print(c)
        print(d)
    
    fun01(1,2,3)
    

    如上 当我们调用函数时,发现 a=1,b=2,c=3,d=1,我们传参的时候没有指定传给谁 他会按位置顺序一 一 匹配

    指定传参

    def fun01(a,b,c,d=1):
        print(a)
        print(b)
        print(c)
        print(d)
    
    fun01(b=1,c=2,a=3)
    

    如上 当我们调用这个函数时,发现打印出来 3、1、2、1 因为我们在传参的时候指定参数名等于对应的值

    可变参数
    *args:接收到的所有按照位置参数方式传递进来的参数,是一个元组类型
    **kw:接收到的所有按照指定参数方式传递进来的参数,是一个字典类型

    def fun02(*args):
        print(args[1])
    
    fun02(2,3,4)
    

    我们执行上面代码会打印出来一个3出来 ,相等于 传了多个参数他会把这多个参数装进一个元组传进去 如果你想取任意一个值 只需要取对应索引

    def fun03(**kw):
        print(kw)
    
    fun03(a=1,b=3)
    >>> {'a': 1, 'b': 3}
    

    **kw 我们可以看到 我们必须要传一个 一对参数进去 键值 键和值都可以自定义

    1.3 、返回值:return

    当我们调用一个函数并传入参数时 ,我们希望得到一个他加工回来的返回值给我们,
    这个返回值 可以有 也可以没有,没有相当于返回 None,没有情况比较注重过程

    def fun04(a):
        print(a)
        return 20
    	
    fun04(7)
    

    我们看到fun04这个函数 有一个参数a 他的函数体里 只有两句一个是打印这个参数,一个是返回 20 ,但在控制台 我们只看到 输出了 7 ,因为你在调用函数的时候 print(a)这个代码 就是要输出一个7到控制面板,但是return 20 ,他会返回一个20给调用的结果,因为你没有输出到控制台 所以他不会显示 你可以用 print(fun04(7)) 调用这个函数 他会输出一个7和20

    :函数体里面 在执行的过程一旦遇到return 就会结束这个函数 ,return 后面在写任何代码不会执行

    练习:
    1.定义一个函数 求两个数之间的和
    2.定义一个函数,求三个数的最大值
    3.定义一个函数,输入任意三个数字是否能构成三角形



    二、面向对象

      面向对象思想是一种程序设计思想(Object Oriented Programming,简称OOP),这里的对象泛指现实中一切事物,每种事物都具备自己的属性和行为。面向对象思想就是在计算机程序设计过程中,参照现实中事物,将事物的属性特征、行为特征抽象出来,描述成计算机事件的设计思想。 它区别于面向过程思想,强调的是通过调用对象的行为来实现功能,而不是自己一步一步的去操作实现。

    举例
      洗衣服:
      面向过程:把衣服脱下来-->找一个盆-->放点洗衣粉-->加点水-->浸泡10分钟-->揉一揉-->清洗衣服-->拧干-->晾起来
      面向对象:把衣服脱下来-->打开全自动洗衣机-->扔衣服-->按钮-->晾起来
    区别:
      面向过程:强调步骤。
      面向对象:强调对象,这里的对象就是洗衣机。
    特点
      面向对象思想是一种更符合我们思考习惯的思想,它可以将复杂的事情简单化,并将我们从执行者变成了指挥者。
      面向对象的语言中,包含了三大基本特征,即封装、继承和多态。

    类和对象
    环顾周围,你会发现很多对象,比如桌子,椅子,同学,老师等。桌椅属于办公用品,师生都是人类。那么什么是类呢?什么是对象呢?

    什么是类
    类:是一组相关属性和行为的集合。可以看成是一类事物的模板,使用事物的属性特征和行为特征来描述该类事物。
    现实中,描述一类事物:
      属性:就是该事物的状态信息。
      行为:就是该事物能够做什么。
    举例:小猫。
      属性:名字、体重、年龄、颜色。
      行为:走、跑、叫。

    什么是对象
    对象:是一类事物的具体体现。对象是类的一个实例(对象并不是找个女朋友),必然具备该类事物的属性和行为。
    现实中,一类事物的一个实例:一只小猫。
    举例:一只小猫。
      属性:tom、5kg、2 years、yellow。
      行为:溜墙根走、蹦跶的跑、喵喵叫。

    类与对象的关系
      类是对一类事物的描述,是抽象的。
      对象是一类事物的实例,是具体的。
      类是对象的模板,对象是类的实体。

    类的定义
    事物与类的对比
    现实世界的一类事物:
      属性:事物的状态信息。
      行为:事物能够做什么。

    class描述事物也是如此:
      成员变量:对应事物的属性,类的全局变量
      成员方法:对应事物的行为,类中的方法

    一定要记住面向对象最为核心的3大特征:
      1.封装
      2.继承
      3.多态

    2.1 类的定义格式

    定义了一个类

    class MyClass:
    
        def __init__(self, name, age):
            self.name = name
            self.age = age
    
        def run(self):
            print("{name} is running".format(name=self.name))
    
    
    a = MyClass("拜登",70)
    a.run()
    
    
    

    我们通过分析上面的代码 来学习 类的定义

    class Myclass:
    

    我们分析第一行代码,我们通过一个关键字 calss 来定义一类 ,起名为 MyClass,
    类的命名:一般遵循大驼峰式,首字符大写,后面每一个单词的首字符大写

        def __init__(self, name, age):
            self.name = name
            self.age = age
    

    我们看到有一个方法叫 __init__ 这是一个初始化方法,又叫类的 构造方法,当你对类进行实例化的时候,用来初始化实例的属性,name 和 age都是实例的属性
    什么是实例 就是你创建出的对象, 就是你现在能看到的self 代表类的实例,类方法必须包含此参数,且为第一个参数

        def run(self):
            print("{name} is running".format(name=self.name))
    

    我们又看到一个方法 run 这个是这个类的一个普通方法,实例化对象后能够做的行为,并不是所有的类都有的

    a = MyClass("拜登",70)
    a.run()
    

    类实例化 是什么那 就是 a = MyClass("拜登",70) 这行代码,我们对类进行了实例化,创建了一个对象a,在实例化的过程中,我们给a对象赋予了两个属性就是 name = "拜登"和age=70,然后我们又用这个对象让他调了run这个方法

    self
    我们可以看到类里面每一个方法都有一个self参数,它并不是默认参数,这个参数在方法被调用时是不需要传参的,这与之前所学过函数内容相违背, self就是执行方法的对象

    我们用一个id方法查看内存地址 ,来研究一下

    class MyClass:
    
        def __init__(self, name, age):
            print("这是在__init__方法中",id(self))
            self.name = name
            self.age = age
    
        def run(self):
            print("{name} is running".format(name=self.name))
    
    
    a = MyClass("拜登",70)
    a.run()
    print(id(a))
    

    执行后的结果

    这是在__init__方法中 2133936776024
    拜登 is running
    2133936776024
    
    

    我们可以看到self 的地址和 a的地址一模一样 ,那我们可以证明 self 就是a, 类对函数被定义后 任何属于这个类的对象 都是可以使用 这个函数的,所以 谁来调用这个函数,谁就会被绑定self

    对象属性的访问和修改
    只能通过对象来进行

    class MyClass:
    
        def __init__(self, name, age):
            self.name = name
            self.age = age
    
        def run(self):
            print("{name} is running".format(name=self.name))
    
    
    a = MyClass("拜登",70)
    a.run()
    
    print(a.age)
    a.age = 20
    print(a.age)
    

    最后在段代码 我们 输出了对象的age属性,然后又更改为了20 在输出了

    练习面向对象: 请编程 把下面student表数据保存 输出每一个人的各个科目和分数,并计算每个学生的总的分数。

    姓名 英语 数学 语文
    曹操 75 61 95
    刘备 62 43 62
    貂蝉 86 23 62

    2.2 封装

    我们创建一个类,有些属性,有些方法,我们不希望被其他人使用,因为那样很容易就产生错误,那么这时,我们就需隐藏实现的细节,只对外公开我们想让他们使用的属性和方法,这就叫做封装。就好比把一些东西用一个盒子封装起来,只留一个口,内部让你看不见。

    在python里,如果属性和方法前面是双下划线,那么这个属性和方法就变成了私有的属性

    class Dog:
    
        def __init__(self,name,age):
            self.__name = name
            self.__age = age
    
        def __run(self):
            print("run")
    
    
    a = Dog("哈士奇",15)
    
    a.__run()
    print(a.__name,a.__age)
    

    我们看到 属性 __name , __age 和方法 __run() 以双下划线开头,这样的方法和属性,类的对象是无法使用的,通过这种方法,就可以将不希望外部访问的属性和方法隐藏起来。
    属性隐藏起来,并非不让外部使用,而是在使用时收到控制,比如年龄,如果年龄属性定义成age,那么就会出现这样的情况

    a.age = 1000
    

    你见过哪个动物的年龄有10000岁呢,这显然是有问题的,但age属性暴露出来了,别人在使用时就可能会犯这样的错误,所以,为了防止这样的错误发生,就可以将age属性设置成私有的,然后提供一个set_age方法,来设置给age 并且判断一下

    class Dog:
    
        def __init__(self,name,age):
            self.__name = name
            self.__age = age
    
        def set_age(self, age):
            if age > 100 or age < 1:
                raise Exception("年龄范围错误")
            self.__age = age
    
        def get_age(self):
            return self.__age
    
        def __run(self):
            print("run")
    
    a = Dog("哈士奇",15)
    
    a.set_age(5)
    print(a.get_age())
    

    2.3 继承

    一个类可以继承一个或者继承多个父类,新建的类被称之为派生类或者子类,被继承的类是父类,可以称之为基类,超类,继承是实现代码重用的重要方式。

    单继承

    class Car(object):
        def __init__(self, speed, brand):
            self.speed = speed
            self.brand = brand
    
        def run(self):
            print("{brand}在行驶".format(brand=self.brand))
    
    # 燃油车
    class Gasolinecar(Car):
        def __init__(self, speed, brand, price):
            super().__init__(speed, brand)
            self.price = price
    
    
    class Audi(Gasolinecar):
        pass
    
    
    honda = Gasolinecar(130, '本田', 13000)
    honda.run()
    
    audi_car = Audi(100, '奥迪', 10000)
    audi_car.run()
    
    print(issubclass(Audi, Gasolinecar))        # 判断Audi是Gasolinecar的子类
    print(issubclass(Gasolinecar, Car))
    

      继承,意味着子类将“拥有”父类的方法和属性,同时可以新增子类的属性和方法。在Gasolinecar类里,我没有写run方法,但是Gasolinecar的父类定义了run方法,因此,Gasolinecar也有这个方法,因此这个类的对象honda可以使用run方法。
      Audi类没有定义任何方法,但是它继承了Gasolinecar,因此,Gasolinecar有的属性和方法,它都拥有,这里就包括了__init__方法。
      super()可以用来调用父类的方法,Gasolinecar多传了一个price属性,其父类的__init__方法里有两个参数,因此,可以先调用父类的__init__方法初始化speed, brand,然后在初始化price

    多继承
      大部分面向对象的编程语言(除了C++)都只支持单继承,而不支持多继承,因为多继承不仅增加编程复杂度,而且容易导致莫名其妙的错误。
      Python虽然支持多继承,但不推荐使用多继承,推荐使用单继承,这样可以保证编程思路更清晰,也可以避免不必要的麻烦。
      当以一个子类有多个直接父类时,该子类会继承得到所有父类的方法,但是如果其中有多个父类包含同名方法会发生什么?此时排在前面的父类中的方法会“遮蔽”后面父类中的方法。

    class Person():
        def person_walk(self):
            print("走路")
    
    
    class Wolf():
        def wolf_run(self):
            print("奔跑")
    
    
    class WolfMan(Person, Wolf):
    
        def __init__(self):
            pass
    
    a = WolfMan()
    
    a.person_walk()
    a.wolf_run()
    

    2.4 多态

      面向对象的多态依赖于继承, 因为继承,使得子类拥有了父类的方法, 子类的方法与父类方法重名时是重写, 同一类事物,有多重形态, 这就是面向对象概念里的多态,多态使得不同的子类对象调用相同的 类方法,产生不同的执行结果,可以增加代码的外部调用灵活度。

    class Base():
        def print(self):
            print("base")
    
    
    class A(Base):
        def print(self):
            print("A")
    
    a = A()
    a.print()
    

    父类和子类都有print方法,那么子类A的对象a调用print方法时,调用的是谁的print方法呢?
    答案是子类的print方法,如果A类没有定义print方法,那么a.print()调用的是父类的print方法,但是A类定义了print方法,这种情况称之为重写,A类重写了父类的print方法。

    继承时,子类“拥有”父类的方法和属性,但这种拥有不是真实意义上的拥有

    class Base():
        def print(self):
            print("base")
    
    
    class A(Base):
        pass
    
    
    print(id(Base.print))
    print(id(A.print))
    

    Base.print 和 A.print 的内存地址是相同的,这说明他们是同一个方法。执行A.print时,python会寻找print方法,它会先从A类的定义中寻找,没有找到,然后去A的父类里寻找print方法,如果还是找不到,就继续向上寻找。

    这便是子类拥有父类属性和方法的真相

    多态表现:同一类事物,有多重形态

    class Animal:
        def run(self):
            raise NotImplementedError
    
    class People(Animal):
        def run(self):
            print("人在行走")
    
    
    class Pig(Animal):
        def run(self):
            print("猪在跑")
    
    
    p1 = People()
    p1.run()
    
    p2 = Pig()
    p2.run()
    

    People和 Pig 都继承了Animal,都是动物,是同一类事物,他们都有run方法,但是最终的运行结果却不一样,这就是多态,同一类事物有多种形态。

  • 相关阅读:
    第一天 学习绪论
    我的java学习道路
    windows2003 iis+dedecms 4.0701版本,登录后台显示空白
    iis+php+mysql
    net 连mysql奇怪问题
    Windows 2008安装SQL 2008图解
    注册码
    [VS2013]如何闪开安装VS2013必须要有安装IE10的限制
    net SqlBulkCopy拷贝数据的问题
    Android应用与系统安全防御
  • 原文地址:https://www.cnblogs.com/niunai/p/15066692.html
Copyright © 2020-2023  润新知