Python的零基础内容(三)

day03 python的函数

函数的创建和调用

函数的作用: 执行特定任务,和完成特定功能的一段代码。1复用代码2隐藏实现细节3提高可维护性4提高可读性便于调试

函数的创建: *对齐使用
def 函数名 ([输入参数])
****函数体
****[return xxx]

函数的调用参数传递

  • 位置实参,根据形参对应形参的位置进行参数传递
  • 想要将序列中的每一个元素都转换为位置实参,需要再调用时列表前加* fun(*lis)
  • 关键字实参,根据形参名称进行实参传递 调用时fun(a=10,b=20)
  • 想要将字典中的每一个键值对都转换为关键字实参,需要在调用时字典前加** fun(**dict)
  • 如果一个函数的参数有想利用位置参数的也有想利用关键字参数的,需要在分隔处添加* 定义时: fun(a,b,*,c,d)则a,b需要使用位置传参,c,d使用关键字传参。调用时:fun(10,20,c=10,d=20)

在函数调用时中进行参数传递

  • 如果时不可变对象,在函数体的修改不会影响实参的值。

  • 如果是可变对象,在函数体的修改会影响到实参的值。

def fun(age1,age2):
    print('age1',age1)
    print('age2',age2)
    print('age1type', type(age1))
    print('age2type',type(age2))
    age1=100
    age2.append(10)
    print('age1',age1)
    print('age2',age2)
n1=11
n2=[11,22,33]
print('n1',n1)
print('n2',n2)
fun(n1,n2)
print('n1',n1)
print('n2',n2)
"""
n1 11
n2 [11, 22, 33]
age1 11
age2 [11, 22, 33]
age1type <class 'int'>
age2type <class 'list'>
age1 100
age2 [11, 22, 33, 10]
n1 11
n2 [11, 22, 33, 10]
"""

函数的返回值

  1. 如果函数的返回值函数执行完毕后不需要调用处理数据时,return不需要书写
  2. 函数的返回值如果只有一个,则直接返回该类型变量值
  3. 函数的返回值如果有多个,则返回的结果为一个元组(’‘,[],10)
def fun(num):
    odd=[]
    even=[]
    for i in num:
        if i%2:
            odd.append(i)
        else:
            even.append(i)
    return odd,even
print(fun([1,2,3,4,5,6,7,8,9,0]))
"""
([1, 3, 5, 7, 9], [2, 4, 6, 8, 0])
"""

函数的参数类型

默认参数值类型

def fun(a,b=10):
    print(a,b)
fun(10)
fun(100,200)#不指定默认10,指定默认

个数可变的位置形参

定义函数时,无法事先确认传递的位置实参的个数时,使用可变的位置参数。使用*定义个数可变的位置形参,结果为一个元组

可变参数的参数类型会被定义为元组。使用过程不能改变引用!!!可变的位置参数只能有一个

def fun(*args):
    print(args)
    print(args[0])
    print('argstype',type(args))
fun(10)
fun(10,20)
fun(10,20,30)
"""
(10,)
10
argstype <class 'tuple'>
(10, 20)
10
argstype <class 'tuple'>
(10, 20, 30)
10
argstype <class 'tuple'>
"""

个数可变的关键字形参

定义函数时,无法事先确定传递的关键字实参的个数时,使用可变的关键字形参,是用定义个数可变的关键字形参,结果为一个字典**

个数可变的关键字参数只能有一个

def fun(**kwargs):
    print(kwargs)
fun(a=10)
fun(a=10,b=20,c=30)
"""
{'a': 10}
{'a': 10, 'b': 20, 'c': 30}
"""

在一个函数的定义过程当中,既有个数可变的关键字形参,也有个数可变的位置形参,要求个数可变的位置形参,放在个数可变的关键字形参之前!

函数定义的形参的顺序问题

def fun1(a,b,*,c,d,**kwargs):
    pass
def fun2(*args,**kwargs):
    pass
def fun3(a,b=10,*args,**kwargs):
    pass
"""

"""

变量的作用域

程序代码能够访问变量的区域,根据变量的有效范围可分为:

  • 局部变量 函数内定义并使用的变量,只在函数内部有效,局部变量使用**global声明,**这个变量就会成全局变量。
  • 全局变量 **函数体外定义的变量。**可用于函数的内外。
name='hello'
def fun():
    global a
    a=10
    print(a,name)
fun()
print(a,name)
"""
10 hello
10 hello
"""

递归函数

如果一个函数的函数体内调用了该函数本身,该函数就称为递归函数

**组成部分:**递归调用和递归终止条件

调用过程:每次递归调用一次函数,都会在栈内存分配一个栈帧每次执行完一次函数,都会释放相应的空间。

递归的优缺点:缺点:占用的内存多,效率低下。优点:思路和代码简单

书写阶乘函数

def fun(a):
    if a==1:
        return 1
    else:
        return a*fun(a-1)
print(fun(3))

斐波那契数列

def fun(a):# 第几个位置上的数
    if (a==1):
        return 1
    elif a==2:
        return 1
    else:
        return fun(a - 1) + fun(a - 2)
def fun1(a):
    f1=1
    f2=1
    while a>0:
        print(f1,f2,end=' ')
        f1=f1+f2
        f2=f1+f2
        a-=1
print(fun(3))
print(fun1(3))

day04 bug的调试

bug

bug叫做马克2号

Debug调试。基础语法错误:

  • 漏掉:
  • 缩进错误
  • 英文字符中文字符
  • 字符串和数字拼接在一起
  • 没有定义变量就使用
  • ==与=的使用

函数知识点使用错误:

  • 索引越界,从0-n-1!!
  • 错误使用类函数与内置函数,类函数需要利用对象调用ste.append(100)内置函数可以直接使用str=input('hello')

不知错误在哪利用print来观看内容 Python中遍历使用for-in很好使用,判断是否序列,元组,集合,字典中是否存在某项可以直接用in not in来判断

lst=[{'rating':[9.7,2062398],'id':'1292050','type':['犯罪','剧情'],'title':'肖申克的救赎','actors':['蒂姆·罗宾斯','摩根·弗里曼']},
     {'rating':[9.6,1528760],'id':'1291540','type':['爱情','剧情','同性'],'title':'霸王别姬','actors':['张国荣','张丰毅','巩俐','葛优']}]

name=input('请输入你要查询的演员:')

for item in lst:
    if name in item['actors']:
        print(name+'出演了:'+item['title'])
        
"""
请输入你要查询的演员:葛优
葛优出演了:霸王别姬
"""

异常处理机制try-except

被动掉坑,就是情况考虑无法使用代码来过分限制,像除法中两个数必须为整数,且除数不得为0.情况时我们需要异常情况处理机制,try一下,多except结构捕获异常的顺序需要按照先子类后父类的顺序,为了避免遗漏可能出现的异常,可以在最后增加BaseException

try:
    可能出现异常的正常代码
except ZeroDivisionError:###什么类型的错误时!执行异常情况之后继续走!
    print('除数不得为零')
except ValueError:
    print('不能将字符串转化为数字')
except BaseException as e:
    print(e)

复制当前文件新增加一个新的文件代码,按住F5

try-except-else

如果try块中没有抛出异常,则执行else块,如果try中抛出异常,则执行except块

try-except-else-finally

finally块无论是否发生异常都会被执行,能常用来释放try块中申请资源!

常见的异常类型:

描述异常类型
数学计算的异常除0的异常ZeroDivisionError
列表中没有此索引!IndexError 下标越界情况
映射中没有这个键KeyError
未声明或未初始化对象NameError
Python语法错误SyntaxError
传入无效的参数ValueError

traceback模块打印异常信息

import traceback
try:
    print('-----------------------------------------')
    print(1/0)
except:
    traceback.print_exc()
"""
Traceback (most recent call last):
  File "D:/pycharmProject/fist.py", line 4, in <module>
    print(1/0)
ZeroDivisionError: division by zero
-----------------------------------------
"""

pycharm的debug自行阅读

day05 面向对象编程

多个类似的事物组成的群体的统称,能够帮助我们快速理解和判断事物的性质!

不同额数据类型就是不同的类

type就可以查看数据的类型

对象类的实例具体的一个东西!

**一切皆对象!!!**10,‘name’,dict,list,tuple,str.

类的创建

class 类名:

​ pass

类是由:类属性,实例方法,静态方法,类方法组成!!!Student就是类对象,因为Python一切皆对象

class Student:##大驼峰的命名,每个单词的首字母大写,其余要小写
    pass
#一切皆对象,这是和其他面向对象的语言的不同
print(id(Student))
print(type(Student))
print(Student)
"""
2294471727072///开辟了内存空间
<class 'type'>///有类型
<class '__main__.Student'>///有值
"""
class Student:##大驼峰的命名,每个单词的首字母大写,其余要小写
    advice='济南'    #类属性!!因为类是有空间的所以里面的变量可以赋值,且python中的变量是指向型的

    #赋值函数,相当于java中的构造函数
    def __init__(self,name,age):
        self.name=name  #self.name叫实例属性,将局部变量赋值给实体属性
        self.age=age
    ##实例方法,类内的叫方法参数要有self
    def eat(self):
        print('这是实例方法,普通的方法')
    #静态方法 无参数
    @staticmethod
    def method():
        print('此处为静态方法是在staticmethod模块中')
    #类方法,参数叫cls为一个类
    @classmethod
    def cm(cls):
        print('此处为类方法是在classmethod模块中')
"""
他声明的这个类其实叫类对象!
"""

对象的创建

类的实例化 语法是实例名=类名() stu=Student()有了实例就可以调用类中的内容。

class Student:
    advice='济南'   
    def __init__(self,name,age):
        self.name=name  
        self.age=age
    def eat(self):
        print('这是实例方法,普通的方法')
    @staticmethod
    def method():
        print('此处为静态方法是在staticmethod模块中')
    @classmethod
    def cm(cls):
        print('此处为类方法是在classmethod模块中')
stu=Student('张三',20)
print(id(stu))
print(type(stu))
print(stu)    ##输出对象值时就是对象的内存地址和id(stu)的值是一样的一个二进制一个十六进制
"""
3092414309040
<class '__main__.Student'>
<__main__.Student object at 0x000002D00241A2B0>
"""

调用方法

对象名.方法名

类名.方法名(对象)

stu.eat()
print(stu.name)
print(stu.age)
Student.eat(stu)
"""
这是实例方法,普通的方法
张三
20
这是实例方法,普通的方法
"""

类属性,类方法,静态方法

类属性:类中方法外的变量称为类属性,被该类的所有对象所共享

类方法:使用@classmetho修饰的方法,使用类名直接访问的方法

静态方法:使用@staticmethod修饰的方法,使用类名直接访问的方法

print(Student.advice)#访问类属性
Student.method()#调用静态方法
Student.cm()#调用类方法
"""
济南
此处为静态方法是在staticmethod模块中
此处为类方法是在classmethod模块中
"""

动态绑定属性和方法

一个类可以创建N个Student类的实例对象,每个实体对象的属性值不同

stu1=Student('张三'20)
stu1.gender='女'  ##只给张三加性别,其他对象没有无法使用哦!。像是字典中添加键值对一样,有则修改值,没有则添加
print(stu1.name,stu1.age,stu1.gender)
def show():
    print('我是一个动态的函数')
stu1.show=show##像动态的变量一样,不需要加括号,保持前后名字相同
stu1.show()
"""
张三 20 女
我是一个动态的函数
"""

_init_()中的变量是所有对象都拥有的内容。

面向对象的三大特征

  • 封装 提高程序的安全性

    • 将数据和行为包装到类对象中,在方法内部对属性进行操作,在类对象的外部调用方法。这样,无需关心方法内部的具体实现细节。从而隔离了复杂度。

    • 在python中没有专门的修饰符用于属性的私有,如果该属性不希望再类对象外部被访问,前面使用两个“_”表示私有

    •     def __init__(self,name,age):
              self.name=name  #self.name叫实例属性,将局部变量赋值给实体属性
              self.__age=age  ##age将不能在类外使用,只能被类内方法所调用,属性名相应的也变成来了__age
          def show(self):
              print(self.name,self.__age)
      #类外部:
      stu=Studen('张三',20)
      stu.show()
      #要想强制使用被隐藏的变量属性使用dir(stu)观察到隐藏的属性名:
      print(dir(stu))
      print(stu._Student__age)
      """
      张三 20
      ['_Student__age', '__class__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__le__', '__lt__', '__module__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__', 'advice', 'cm', 'eat', 'gender', 'method', 'name', 'show']
      20
      """
      
  • 继承 提高代码的复用性

    • class 子类名字(父类1,父类2):
          pass
      class Person:
          def __init__(self, name, age):
              self.name = name
              self.age = age
          def info(self):
              print('姓名:{0},年龄:{1}'.format(self.name, self.age))
      class Student(Person):
          def __init__(self,name,age,stu_no):
              super().__init__(name,age)
              self.stu_no=stu_no
      stu=Student('李四',20,2308097)
      stu.info()
      """
      姓名:李四,年龄:20
      """
      
    • 如果一个类没有继承任何类,则默认继承object

    • python支持多继承

      class A:
      pass
      class B:
      pass
      class C(A,B):
      pass

      
      
    • 定义子类时,必须在其构造函数中调用父类的构造函数构造函数就是_init_(self)…子类需要利用super().__init__(name,age)

    • 方法的重写,重写继承父类的方法!必须函数名相同!子对象调用时调用子类重写的方法

      • class Person:
            def __init__(self, name, age):
                self.name = name
                self.age = age
            def info(self):
                print('姓名:{0},年龄:{1}'.format(self.name, self.age))
        class Student(Person):
            def __init__(self,name,age,stu_no):
                super().__init__(name,age)
                self.stu_no=stu_no
            def info(self):
                super().info()
                print(self.stu_no)
        stu=Student('李四',20,2308097)
        stu.info()
        """
        姓名:李四,年龄:20
        2308097
        """
        
    • object类:是所有类的父类,因此所有类都有object类的属性和方法。内置函数dir()可以查看指定对象所有的属性,_str_()方法用于返回一个对于“对象的描述”,对应于内置函数str()经常用于print()方法,帮助我们查看对象的信息,所以经常会对__str__()进行重写,这个函数使得我们在使用print()打印对象时不在是它所占用的内存地址了

      • def __str__(self):
            return f'我的名字是{self.name},我的年龄是{self.age}'
        stu=Student('张三',20)	
        print(stu)
        #我的名字是张三,我的年龄是20
        
  • 多态 提高程序的可扩张性和可维护性

    • 具有多种形态,即便不知道一个变量所引用的对象到底是什么类型,仍然可以通过这个变量调用方法,在运行过程中根据变量所引用对象的类型,动态决定调用哪个对象中的方法。这个对象具备所要调用的方法就会调用该对象的方法

    • class Animal:
          def eat(self):
              print('吃饭了')
      class(Animal):
          def eat(self):
              print('猫吃🐟')
      class(Animal):
          def eat(self):
              print('狗吃骨头')
      class Person:
          def eat(self):
              print('人啥都吃')
      def fun(a):
          a.eat()
      fun(Animal())
      fun(())
      fun(())
      fun(Person())
      """
      吃饭了
      猫吃🐟
      狗吃骨头
      人啥都吃
      """
      

静态语言和动态语言

静态语言实现多态的三要素:继承,方法重写,父类引用指向子类对象(C++就是)

动态语言的多态崇尚鸭子类型当看到一个鸟走起来像鸭子、游泳起来像鸭子、收起来也想鸭子,那么这只鸟就可以称为鸭子。在鸭子类型中,不需要关心对象是什么类型,到底是不是鸭子,只关心对象的行为。只要它具有eat()这个方法就可以被多态使用

特殊的属性和方法

–|--|–|

|名称|描述

特殊属性|_dict_|获得类对象或实例对象所绑定的所有属性和字典

名称描述
特殊属性_dict_获得类对象或实例对象所绑定的所有属性字典
特殊方法_len_通过重写_len_()方法,让内置函数len()的参数可以是自定义类型
_add_通过重写__add()__方法,可使自定义对象具有”+“功能
_new_用于创建对象
_init_对创建的对象进行初始化

常用属性像:dict,class,bases,base,mro

class A:
    pass
class B:
    pass
class C(A,B):
    advice='zhaozhuang'
    def __init__(self,name,age):
        self.name=name
        self.age=age
x=C('张三',20)
print(x.__dict__) #实例对象的属性字典
print(C.__dict__) #类对象的属性字典
print(x.__class__) #对象所属的类
print(C.__bases__)  #C类的父类类型的元组
print(C.__base__)  #C类离的最近的父类
print(C.__mro__) #类的层次结构
print(A.__subclasses__()) #子类的列表
"""
{'name': '张三', 'age': 20}
{'__module__': '__main__', 'advice': 'zhaozhuang', '__init__': <function C.__init__ at 0x000001752DD77940>, '__doc__': None}
<class '__main__.C'>
(<class '__main__.A'>, <class '__main__.B'>)
<class '__main__.A'>
(<class '__main__.C'>, <class '__main__.A'>, <class '__main__.B'>, <class 'object'>)
[<class '__main__.C'>]
"""

add和len函数的使用

class Student:
    def __init__(self,name):
        self.name=name
    def __add__(self, other):
        return self.name+other.name
    def __len__(self):##重写长度函数
        return len(self.name)
stu1=Student('张三三')
stu2=Student('李四')
s=stu1+stu2 #实现了两个对象的加法运算(重写了__add__()函数)
print(s)
lst=[11,22,33,44]
print('lst内置函数计算长度:',len(lst))
print('lst的类函数计算长度:',lst.__len__())
##—__len__()重写了内置函数len()    
#当我们要获得某一对象的长度时,我们可以重写类的__len__()的函数
print('stu1的长度:',len(stu1))
print('stu2的长度:',len(stu2))
"""
张三三李四
lst内置函数计算长度: 4
lst的类函数计算长度: 4
stu1的长度: 3
stu2的长度: 2
"""

new和init

class Person:
    ##new在前,先创建对象
    def __new__(cls, *args, **kwargs):
        print(f'new已执行,cls的id值为{id(cls)}')
        obj=super().__new__(cls)
        print(f'创建的对象的id为{id(obj)}')
        return obj
    ##初始化对象的
    def __init__(self, name, age):
        print(f'init被调用了,self的id值为:{id(self)}')
        self.name = name
        self.age = age
print(f'object这个类对象的id为{id(object)}')
print(f'Person这个类对象的id为{id(Person)}')

p1=Person('张三',20)

print(f'p1这个Person这个实例对象的id为{id(p1)}')
"""
object这个类对象的id为140720163240784
Person这个类对象的id为2267325734208
new已执行,cls的id值为2267325734208
创建的对象的id为2267332315744
init被调用了,self的id值为:2267332315744
p1这个Person这个实例对象的id为2267332315744
"""

类的赋值和浅拷贝

变量的赋值操作,只是形成两个变量,实际上还是指向同一个对象

浅拷贝 python拷贝一般丢失浅拷贝,拷贝时,对象包含的子对象内容不拷贝,因此,源对象与拷贝对象会引用同一个子对像

  • class Cpu:
        pass
    class Disk:
        pass
    class Computer:
        def __init__(self,cpu,disk):
            self.cpu=cpu
            self.disk=disk
    cpu=Cpu()
    disk=Disk()
    computer=Computer(cpu,disk)
    import copy
    computer1=copy.copy(computer)
    print(computer,computer.cpu,computer.disk)
    print(computer1,computer1.cpu,computer1.disk)
    """
    <__main__.Computer object at 0x000002D0B07291C0> <__main__.Cpu object at 0x000002D0B0756A90> <__main__.Disk object at 0x000002D0B0729700>
    
    <__main__.Computer object at 0x000002D0B079B070> <__main__.Cpu object at 0x000002D0B0756A90> <__main__.Disk object at 0x000002D0B0729700>
    """
    

深拷贝 使用copy模块的deepcopy函数,递归拷贝对象中包含的子对象,源对象和拷贝对象所有的子对象也不相同。

  • import copy
    computer1=copy.deepcopy(computer)
    print(computer,computer.cpu,computer.disk)
    print(computer1,computer1.cpu,computer1.disk)
    """
    <__main__.Computer object at 0x0000027849F491C0> <__main__.Cpu object at 0x0000027849F76A90> <__main__.Disk object at 0x0000027849F49700>
    
    <__main__.Computer object at 0x0000027849FBB1F0> <__main__.Cpu object at 0x000002784A0C6CA0> <__main__.Disk object at 0x000002784A0C6D60>
    """
    
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值