江西农业大学Python期末复习3函数递归python面向对象编程

函数实现代码复用

  • 1.函数实现代码复用
    • 1.1函数的定义和调用
    • 1.2函数的参数和返回值
  • 2.面向对象编程
    • 2.1面向对象的基本概念
    • 2.2创建类与对象
    • 2.3属性和方法
    • 2.4构造方法和析构方法
    • 2.5属性和方法的访问控制
    • 2.6继承
    • 2.7多态
    • 2.8封装
    • 2.9单例模式

1.函数实现代码复用

1.1函数的定义和调用

​ 你可以定义一个由自己想要功能的函数,以下是简单的规则:

  • 函数代码块以 def 关键词开头,后接函数标识符名称和圆括号 ()
  • 任何传入参数和自变量必须放在圆括号中间,圆括号之间可以用于定义参数。
  • 函数的第一行语句可以选择性地使用文档字符串—用于存放函数说明。
  • 函数内容以冒号 : 起始,并且缩进。
  • return [表达式] 结束函数,选择性地返回一个值给调用方,不带表达式的 return 相当于返回 None。
#Python 定义函数使用 def 关键字,一般格式如下:
def 函数名(参数列表):
    函数体
    
#更复杂点的应用,函数中带上参数变量:
def max(a, b):
    if a > b:
        return a
    else:
        return b
 
a = 4
b = 5
print(max(a, b))

def print_xing():
    print("***************************")
def print_text():
    print("这是一个函数调用实例!")

print_xing()
print_text()
print_xing()

#运行结果
***************************
这是一个函数调用实例!
***************************

1.2函数的参数和返回值

  • 形参与实参
def max(a,b):
    if a>b:
        return a
    else:
        return b

x=int(input("请输入一个数x:"))
y=int(input("请再输入一个数y:"))
z=max(x,y)
print("较大数为:",z)

​ 分析这个比较最大数,其中max()函数括号内的a,b就是该函数的形参;而在调用函数时,括号内的x和y则是传递给该函数的实参

  • 必备参数

​ 必备参数须以正确的顺序传入函数。调用时的数量必须和声明时的一样。

​ 调用 print_text()函数,你必须传入一个参数,不然会出现语法错误:

def print_text(x,y):
    print(x,y)

print_text("hello","Final Exam!")

print_text("hello")
#运行结果
hello Final Exam!
Traceback (most recent call last):
  File "D:/pycharm/py代码/Python期末/函数调用.py", line 26, in <module>
    print_text("hello")
TypeError: print_text() missing 1 required positional argument: 'y'
  • 关键字参数

​ 关键字参数和函数调用关系紧密,函数调用使用关键字参数来确定传入的参数值。

​ 使用关键字参数允许函数调用时参数的顺序与声明时不一致,因为 Python 解释器能够用参数名匹配参数值。

​ 以下实例在函数 fun() 调用时使用参数名:

def fun(discount,price):
    print("商品折扣:",discount)
    print("商品价格:",price)
    return
fun(price=100,discount=0.4)
#运行结果
商品折扣: 0.4
商品价格: 100

  • 默认参数

​ 调用函数时,如果没有传递参数,则会使用默认参数。以下实例中如果没有传入 price 参数,则使用默认值:

def fun(discount,price=100):
    print("商品折扣:",discount)
    print("商品价格:",price)
    return
fun(0.4)
#运行结果
商品折扣: 0.4
商品价格: 100

**值得注意的是,在定义默认值参数的函数时,只能将默认值赋给最右端的参数,否则会出现语法错误。**在Pycharm中早已经出现报错了。

def fun(discount=0.4,price):
    print("商品折扣:",discount)
    print("商品价格:",price)
    return
fun(100)
#运行结果
    def fun(discount=0.4,price):
           ^
SyntaxError: non-default argument follows default argument
  • 不定长参数

​ 你可能需要一个函数能处理比当初声明时更多的参数。这些参数叫做不定长参数,和上述 2 种参数不同,声明时不会命名。只需在参数列表最右侧增加一个带*的参数,基本语法格式如下:

def 函数名([形参列表] *args):
    函数体
#例子
def f(x,y,*args):
    print(x)
    print(y)
    print(args)
f(10,9,8,7,6,5,4,3,2,1)
#运行结果
10
9
(8, 7, 6, 5, 4, 3, 2, 1)
  • 函数的返回值

return [表达式] 语句用于退出函数,选择性地向调用方返回一个表达式。不带参数值的 return 语句返回 None。可以返回0个、1个或一组值,以下实例演示了 return 语句的用法:

def fun(discount,price):
    price=discount*price
    print("商品折扣:",discount)
    print("商品价格:",price)
    return price
fun(0.5,100)
#运行结果
商品折扣: 0.5
商品价格: 50.0

  • 匿名函数

​ 所谓匿名,意即不再使用 def 语句这样标准的形式定义一个函数。

  • lambda 只是一个表达式,函数体比 def 简单很多。
  • lambda用于定义简单的、能够在一行内表示的函数,返回一个函数类型;lambda函数能接受任何数量的参数,但只能返回一个表达式,同时只能处理输出的内容,不可包含命令或多个表达式,匿名函数不能直接调用print,因为lambda需要一个表达式。
函数名=lambda[参数列表] : 表达式

sum=lambda arg1,arg2:arg1+arg2;
print("total:",sum(20,50))

#运行结果
total: 70

2.面向对象编程

2.1面向对象的基本概念

  • 对象

    ​ 现实世界中客观存在的事物称作对象,任何对象都具有各自的特征(属性)和行为(方法)。**对象的特征用数据来表示,称为属性;对象的行为用程序代码实现,称为对象的方法。**总之,任何对象都是由属性和方法组成的。

  • ​ 类是具有相同属性和行为的一组对象的集合,它为属于该类的全部对象提供了统一的抽象描述。任何对象都是某个类的实例。

    用来描述具有相同的属性和方法的对象的集合。它定义了该集合中每个对象所共有的属性和方法。对象是类的实例。

  • 消息

    ​ 一个系统由若干个对象组成,各个对象之间通过消息相互联系,相互作用。消息是一个对象要求另一个对象实施某项操作的请求。发送者发送消息,在一条消息中,需要包含消息的接收者和要求接收者执行某项操作的请求,接收者通过调用相应的方法响应消息,这个过程被不断的重复,从而驱动整个程序的运行。

  • 封装

    ​ 封装是指把对象的数据(属性)和操作数据的过程(方法)结合在一起,构成独立的单元,它的内部信息对外界是隐蔽的,不允许外界直接存取对象的属性,只能通过类提供的外部接口与对该对象实施各项操作,保证了程序中数据的安全性。

    类是数据封装的工具,对象是封装的实现。

  • 继承

    ​ 继承反映的是类与类直接抽象级别的不同,根据继承与被继承的关系,可分为基类和衍类,基类也称为父类,衍类也称为子类,正如"继承"这个词的字面含义一样,子类将从父类那里获得所有的属性和方法,并且可以对这些获得的属性和方法进行改造,使之具有自己的特点。

  • 多态

    ​ 多态是指统一名字方法产生了多种不同的动作行为,也就是不同的对象收到相同的消息时产生不同的行为方式。该多态的概念应用于面向对象程序设计,增强了程序对客观世界的模拟性,使得对象程序具有更好的可读性。

2.2创建类与对象

  • 定义类
    在python中,用class关键字来定义类,定义类的语法格式如下:

    class ClassName:
        <statement-1>
        .
        .
        .
        <statement-N>
        
        
    #应用示例
    class CC:
        x=10
        y=20
        z=30
        def show(self):
            print((self.x+self.y+self.z)/3)
    
    b=CC()
    b.x=30
    b.show()
    #运行结果
    26.666666666666668
    
  • 对象的创建和使用

    在Python中,用赋值的方式创建类的实例,一般格式为:

    对象名=类名(参数列表)

    创建对象后,可以使用“.”运算符,通过实例来防卫这个类的属性和方法(函数)。实例如上。

2.3属性和方法

  • 类属性和实例属性

    • 类属性

      类属性为所有类对象的实例对象所共有。类属性通常在类体中初始化。对于公有的类属性,在类外可以通过类对象和实例对象访问。

      类的私有属性

      __private_attrs:两个下划线开头,声明该属性为私有,不能在类的外部被使用或直接访问。在类内部的方法中使用时 self.__private_attrs

      class Person:
          name='brenden'
          __age=18
      p=Person()
      print(p.name)
      print(Person.name)
      print(p.__age)#报错,不能在类外通过实例对象访问私有的类属性
      print(Person._age)#报错,不能在类外通过类对象访问私有的类属性
      
      
    • 实例属性

      实例属性不需要在类中显示定义,而应该在_ _ init _ _ 构造函数中定义,定义时以"self."作为前缀,实例属性属于特定的实例。所有的实例属性最好在 _ _ init _ _ 中给出。实例属性在内部通过“self.”访问,在外部通过对象实例访问。

      class Student:
          def __init__(self,name,age,grade):
              self.name=name
              self.age=age
              self.grade=grade
          def say_hi(self):
              print('I am a student ,my name is ' ,self.name)
      
      s1=Student('王子',21,3)
      
      s1.say_hi()
      print(s1.grade)
      
      s2=Student('公主',20,2)
      
      s2.say_hi()
      print(s2.grade)
      
      #运行结果
      I am a student ,my name is  王子
      3
      I am a student ,my name is  公主
      2
      

      上述例子中,Student类中定义了实例属性name,age和grade。s1、s2是Student的两个实例,这两个实例分别拥有自己的属性值,有别于其他对象。实例的属性可以向其他变量一样进行操作。

      s1.grade=s1.grade+1
      
  • 类的方法
    方法是与类相关的函数。方法和函数不同,函数时封装操作的小程序。方法是定义在类内部的函数,并且定义方法与普通函数有所不同。类的方法主要有三种类型:实例方法、类方法和静态方法,不同的方法有不用的使用场景和声明调用形式,不同的方法也具有不同的访问限制。实例方法是属于实例的方法,通过实例名方法名调用,该方法可以访问类属性、实例属性、类方法、实例方法和静态方法。类方法是属于类的方法,可以通过实例名方法名,也可以通过类名方法名调用。类方法不能访问实例属性和实例方法。静态方法是与类实例对象无关的方法,调用形式同类方法类似。

  • 方法的声明和调用

  • 在类的内部,使用def关键字可以为类定义一个方法。与一般函数定义不同,类方法必须包含对象本身的参数,通常为self,且为第一个参数。声明方法的语法格式如下:

    ​ def 方法名(self,[形参列表])

    ​ 函数体

    方法调用的语法格式如下:

    ​ 对象.方法名([参数列表])

    在调用方法时,第一个参数self不需要用户为其赋值,Python自动把对象实例传递给参数self。

  • 实例方法

    实例方法是在类中经常定义的成员方法,它至少有一个参数并且必须以实例对象作为其第一个参数,一般以“self”作为第一个参数。在类外,实例方法只能通过实例对象去调用。

#定义Person类,通过实例调用实例方法
class Person:
    place = 'jiangxijxau'
    def getPlace(self):#实例方法
        return self.place

p=Person()
print(p.getPlace())
print(p.place)
#运行结果
jiangxijxau
jiangxijxau
  • 类方法
    类方法不对特定实例进行操作,在类方法中访问实例属性会导致错误。类方法需要用修饰器"@ classmethod"来标识其为类方法。对于类方法,第一个参数必须是类对象,一般以“cls”作为第一个参数,类方法可以通过实例对象和类对象进行访问。

    类方法还有一个用途就是可以对类属性进行修改。

#定义Person类,定义并调用类方法
class Person:
    place = 'jiangxijxau'
    @classmethod
    def getPlace(cls):
        return cls.place

p=Person()
print(p.getPlace())
print(Person.getPlace())
#运行结果
jiangxijxau
jiangxijxau


#定义Person类,定义并修改类属性
class Person:
    place = 'jiangxijxau'
    @classmethod
    def getPlace(cls):
        return cls.place

    @classmethod
    def setPlace(cls,place1):
        cls.place=place1

p=Person()
p.setPlace("shanghai")
print(p.getPlace())
print(Person.getPlace())
#运行结果
shanghai
shanghai
  • 静态方法
    静态方法需要通过修饰器“@staticmethod”来进行修饰,静态方法不需要多定义参数。

    #定义Person类,定义并调用静态方法
    class Person:
        place='jishui'
        @staticmethod
        def getPlace():
            return Person.place
    print(Person.getPlace())
    #运行结果
    jishui
    

2.4构造方法和析构方法

  • 构造方法

    构造方法 _ _ init _ _ (self,…)在生成对象是调用,可以用来进行一些属性初始化操作,不需要显式去调用,系统会默认执行。构造方法支持重载,如果用户自己没有重新定义构造方法,系统就自动执行默认的构造方法。

    #构造方法并使用示例
    class Person:
        def __init__(self,name):
            self.PersonName=name
        def sayHi(self):
            print('大家好,我是{}。'.format(self.PersonName))
    
    p=Person('泽冷')
    p.sayHi()
    #运行结果
    大家好,我是泽冷。
    
  • 析构方法
    析构方法 _ _ def _ _ (self) 在释放对象时被调用,支持重载,可以在其中进行一些释放资源的操作,不需要显式去调用

    #构造方法并使用示例
    class Test:
        def __init__(self):
            print('构造方法')
        def __del__(self):
            print("析构方法")
        def myf(self):
            print('调用自定义方法')
    
    obj = Test()
    obj.myf()
    del obj
    
    #运行结果
    构造方法
    调用自定义方法
    析构方法
    

2.5属性和方法的访问控制

  • 属性的访问控制
    python中没有像C++中public和private这些关键字来区别公有属性和私有属性,它是以属性命名的方式来区别的,如果在属性名前面加了两个下划线 _ _ ,那么表示私有属性,否则为公有属性。如果在方法名前面加了则说明是私有方法。

  • 方法的访问控制
    在类中可以根据需要定义一些方法,定义方法采用def关键字,在类中定义的方法至少会有一个参数,一般以名为“self”的变量作为该参数,而且需要作为第一个参数。

2.6继承

继承用于指定一个类将从其父类获取其大部分或全部功能。用户对现有类进行修改,来创建一个新的类,称为子类或派生类,原有类称为父类或基类。

#面向对象之继承
class Person(object):
    def __init__(self,name,gender):
        self.name=name
        self.gender=gender
        print('person类 __ini()__.','姓名:',self.name)

class Student(Person):
    def __init__(self,name,gender,score):
        super(Student, self).__init__(name,gender)
        self.score=score
        print('Student类 __ini()__.','姓名:',self.name)

#“__main__”等于当前执行文件的名称
if __name__=="__main__":
    person=Person('张三','男')
    student=Student("李四",'女',100)
    
#运行结果
person类 __ini()__. 姓名: 张三
person类 __ini()__. 姓名: 李四
Student类 __ini()__. 姓名: 李四

  • 多继承
#面向对象之多重继承
class P1():
    def foo(self):
        print("p1-foo")
class P2():
    def foo(self):
        print("P2-foo")
    def bar(self):
        print("P2-bar")
class C1(P1,P2):
    pass
class C2(P1,P2):
    def bar(self):
        print("C2-bar")
class D(C1,C2):
    pass
if __name__=='__main__':
    d=D()
    d.foo()
    d.bar()
#运行结果
p1-foo
C2-bar

子类可以继承一个父类,也可以继承多个父类,这就是多重继承。多重继承的语法格式如上。

2.7多态

多态即多种形态,在运行时确定其状态,在编译阶段无法确定其类型,这就是多态。

多态性指的是:向不同对象发送同一条消息,不同对象在接收时会产生不同的行为(即方法)。所谓消息,就是调用函数,不同的行为就是指不同的实现,即执行不同的函数。

#不使用多态的面向对象程序实现
class ArmyDog(object):
    def bite_enemy(self):
        print('追击敌人')
class DrugDog(object):
    def track_drug(self):
        print('追查毒品')
class Person(object):
    def work_with_army(self,dog):
        dog.bite_enemy()
    def work_with_drug(self,dog):
        dog.track_drug()
person = Person()
person.work_with_army(ArmyDog())
person.work_with_drug(DrugDog())
#运行结果
追击敌人
追查毒品




#使用多态的面向对象程序实现
class Dog(object):
    def work(self):
        pass
class ArmyDog(Dog):
    def work(self):
        print("追击敌人")
class DrugDog(Dog):
    def work(self):
        print("追查毒品")
class Person(object):
    def work_with_dog(self,dog):
        dog.work()
person = Person()
person.work_with_dog(ArmyDog())
person.work_with_dog(DrugDog())
#运行结果
追击敌人
追查毒品

2.8封装

封装其实分为两个层面,第一个层面的封装:创建类和对象会分别创建两者的名称空间,只能用“类名.”或者“实例名.”的方式去访问里面的属性和方法,这就是一种封装。

第二个层面的封装:类中把某些属性和方法隐藏起来(或者说定义成私有的),只在类的内部使用,外部无法访问,或者留下少量接口(函数)供外部访问。在继承中,如果父类不想让子类覆盖自己的方法,可以将方法定义为私有的。

class A:
    def fm(self):
        print('from A')
    def test(self):
        self.fm()
class B(A):
    def fm(self):
        print('from B')
b=B()
b.test()
#运行结果#运行结果
from B


#将fm()定义成私有的,即 _ _ fm (),输出结果就会变成“from A”


class A:
    def __fm(self):
        print('from A')
    def test(self):
        self.__fm()
class B(A):
    def __fm(self):
        print('from B')
b=B()
b.test()
#运行结果#运行结果
from A

2.9单例模式

在某些系统中,为了节省内存资源、保证数据内容的一致性,对某些类要求只能创建一个实例,这就是所谓的单例模式。

单例模式是一种常用的软件设计模式,该模式的主要目的是确保对某一个类还有一个实例存在。

在计算机系统中,还有windows的回收站、操作系统的文件夹系统、应用程序的日志对象、数据库的连接池、网站的计数器、web应用的配置对象、应用程序中的对话框、系统中的缓存等常常被设计成单例。

#创建一个全局唯一的实例对象
class Earth(object):
    __instance = None #定义一个类属性做判断
    def __new__(cls):
        if cls.__instance == None:
            #如果__instance为空证明是第一次创建实例
            #通过父类的__new__(cls)创建实例
            cls.__instance=object.__new__(cls)
            return cls.__instance
        else:
            #返回上一个对象的引用
            return cls.__instance

a=Earth()
print(id(a))
b=Earth()
print(id(b))
#运行结果#运行结果
1846493173704
1846493173704

在Python中,一个类创建实例是通过调用父类object的 _ _ new _ _ (cls)方法来创建的。我们可以通过重写 _ _ new _ _ (cls)方法去实现类只创建一个实例。

你可能感兴趣的:(Python学习,python,pycharm,开发语言)