函数
- 函数定义和调用;
- 函数的返回值;
- 局部变量和全局变量;
- 形参和实参;
- 匿名函数lambda;
函数的定义调用
- 函数的定义:把代码封装到函数内部,函数具有独立功能,然后封装,用的时候就直接调用即可,可以把函数当做一个变量直接使用;----所以定义的时候不执行代码,调用时才执行函数代码
- 函数的调用:调用函数时,执行函数内代码,还可以通过函数的参数,实现函数代码的灵活功能;
- 函数的嵌套:函数中还有一个函数,相当于函数中调用另一个函数,把这个函数就当做一个变量或者表达式即可;
函数的返回值
- 返回值return:函数内容通过return返回给调用者一个值,return可以是常量、变量、表达式;
- return的意义:
- 需求不停的变化,但函数一旦定义函数内部的代码不应该因为需求改变而改变;
- 所以要把因为需求而改变的代码放到函数之外,函数内的代码函数定义完成之后就不要改变了;
python
复制代码
def hello():
print("hello world")
hello() #调用函数
#返回值
def my_sum(a,b): #形参
return a+b #返回值
print(my_sum(2,3))#实参是2,3
局部变量和全局变量
- 局部变量以及他的作用域:
- 函数内部定义的变量就是局部变量;
- 局部变量只能在函数内部使用;
- 不同的函数局部变量名字可以相同,也可以和全局变量重名(但是不建议这样做);
- 定义函数时,局部变量在内存中并不存在,只有在函数调用时才在内存中存在,调用结束后才消失;
- 全局变量和他的作用域:
- 函数外部定义的变量就是全局变量,一般定义在函数上方;
- 全局变量在所有函数内部都可使用;
- 局部变量能解决的问题,不要通过全局变量解决, 尽量少定义全局变量;
- 全局变量只有在程序执行完毕后,才在内存中消失;
- 关键字global:函数内部修改全局变量的值,修改前需要用global修饰全局变量的名字。①所以他只在函数内部使用,②只有在调用函数后,全局变量才被修改,③如果不被调用或者调用前,全局变量维持不变,具体可见下面示例;
python
复制代码
num1=10 #定义全局变量num1
num2=1 #定义全局变量num2
def my_func01():
num1=100 #不是全局变量赋值,而是重新定义了同名局部变量
print(num1)#打印的是局部变量100
def my_func02():
print(num1) #直接使用全局变量
def my_func03():
global num2 #全局变量
num2=3 #全局变量重新赋值
print(num2) #打印的是全局变量3
my_func01() #调用函数,输出是局部变量100
my_func02()#调用函数,输出是全局变量10
print(num1) #直接打印全局变量10,因为在函数中定义的是同名局部变量
print(num2) #打印全局变量num2,他是1
my_func03()#打印全局变量num2,他是3
print(num2) #打印全局变量num2,他是调用后变成了3,所以这块是3
函数的形参实参
- 形参:定义函数时,括号里面的参数,他只能变量----是个变量名;---相当于局部变量;
- 实参:调用函数时,括号里面的参数,他可以是变量、常亮、表达式;---这个时候才能产生值,然后赋值给形参;
- 形参如果是数字、字符串,在函数内部修改了形参的值,实参的值不会改变;
- 但是形参类型如果是列表,集合、字典,形参值的改变,将会影响实参的值----这个是python规定的,同字符串数字不一样,示例:
python
复制代码
#形参是列表的情况,集合和字典同列表一样
a = [1, 2, 3]
def my_func01(a): # a是一个形参,也是属于my_func01函数的局部变量
a[0] = 10 # 修改形参a[0]的值
print(a) # 显示的是全局变量a的值
my_func01(a) # 把全局变量做为实参,来调用函数my_func01
print(a)
- 形参的缺省值:函数调用的时候,没有相应的实参,那么形参会采用缺省值,示例:
python
复制代码
#形参缺省值,缺省值写在最后
def my_func01(a,b=10): #不可以这样写(a=10,b),缺省值必须在最后
print(a,b)
my_func01(1,2) #所有值都提供,输出1,2
my_func01(1)#b的值未提供,使用缺省值,所以输出是1,10
匿名函数
- lambda是个小型的函数,没有def,没有return;
- 语法:lambda 参数1, 参数2, ... : 函数执行代码
- 只有一条语句,且这条语句有个具体的返回值,不能使用print
python
复制代码
my_sum=lambda a,b:a+b
print(my_sum(3,5))
num2=lambda a,b:a if a>b else b #if的写法,和普通代码中的写法不一样
print(num2(3,7))
面向对象
概念介绍
- 类:抽象,模板,同java一样
- 对象:具体,如某一辆具体的车子,同java一样
- 方法:类中的函数;
- 属性:类中的变量;
class
- class:类的关键字
- 实例化:目的是创建对象
- 类中的方法不能直接调用,需要实例化后,通过具体示例调用方法
python
复制代码
#定义类
class Cat:
height=10 #属性
def drink(self): # 方法drink,第一个参数必须是self
print("cat can drink")
def eat(self):
print("cat can eat")
mini=Cat() #实例化,创建对象mini
mini.drink() # 调用的时候,不需要提供self对应的实参
mini.eat()
self参数
- self参数:只在方法内部定义和使用,还可以在方法内部嵌套调用其他方法----但是不能在类的外部使用
- 类的外部如何使用方法和属性:
对象名.方法名、对象名.属性名
python
复制代码
#self的使用
class cat:
def set_name(self):
self.name="tom cat" #使用self在方法内部定义和使用属性
def drink(self): #
print("%s can drink" % self.name)
def eat(self):
print("%s can eat"% self.name)
def demo(self): #使用self在方法内部嵌套调用其他方法
self.eat()
self.drink()
c=cat() #实例化创建对象c
c.set_name()
c.drink()
c.eat()
print("*"*20)
c.name="jery cat" #类的外面使用属性
c.drink() #类的外面使用方法
c.eat()
print("*"*20)
c.demo()
init方法
__init__方法:前面两个下划线,后面两个下划线,实例化时,init自动调用;
- init方法:有形参的时候,对象实例化时就必须提供实参,所以init的形参可以提供缺省值(默认值);
python
复制代码
class car():
def __init__(self,name="BMW"):#name使用缺省值
self.name=name
print("car 被创建了")
def move(self):
print("%s can move" % self.name)
car01=car()
car01.move()
del方法
- del方法:当对象在内存中销毁的时候,自动调用del方法,且只有一个参数self;
- 与init方法对应,实例化时自动调用,有self还可能有多个参数;
- 如果对象是局部的,那么函数执行完毕,自动调用对象的del方法;
- 如果对象是全局的,那么程序执行完毕,自动调用对象的del方法;
- 有没有del方法,程序执行完毕后对象都会自动销毁了,那么del的作用是为了对象从内存中销毁时,有机会能执行一些代码;如果对象从内存中销毁时没有需要执行的代码则可以不需要del方法。
python
复制代码
class cat:
def __init__(self, name = "tom"):
self.name = name
def show_name(self):
print(self.name)
def __del__(self):
print("%s销毁了" % self.name)
c = cat("金渐层") # c是个对象,同时也是一个变量
c.show_name() # 程序执行完毕后,自动调用del方法
返回值注意点
- 函数有无返回值情况:无返回值情况下,不要使用print输出方法;
- my_func01()无返回值,使用print方法时,会输出None,具体见示例
python
复制代码
def my_func01():
print("hello")
my_func01() #输入结果hello
print(my_func01()) #先输出结果为hello ,再输出None--原因:该函数没有return语句,放到print中输出None
def my_func02():
return "hello"
my_func02() #调用函数,无输出结果
print(my_func02()) #输出hello,有return语句,直接通过print输出hello
方法起名注意点
- 函数或者方法起名:需要见名知意
- set:一般用于设置属性名
- get:获取属性名
- show:显示属性名
str方法
__str__方法:只有self,没有其他参数;必须有return以及返回值;
- 可以实现把对象放到print里面显示想要显示的结果;
python
复制代码
class cat:
def __init__(self,name="tom"):
self.name=name
def __str__(self): #类没有str方法,类的实例化的对象放到print里面显示的是对象的内存地址
return self.name
c=cat()
print(c)
三大特性
封装
- 就是把类的属性和方法封装到类的内部,只能在内部使用,不能在类的外部使用;
- 私有属性/方法就是对象不希望公开的属性/方法;
- 私有属性/方法定义:在属性和方法名前面加两个下划线__,这个属性和方法就成为了类的私有属性和方法;
- 私有属性/方法就是对象不希望公开的属性/方法;
python
复制代码
class man:
def __init__(self):
self.name="joe"
self.__weight=200 #私有属性,属性前两个下划线,外部无法访问
self.__psd="123456"
def __drink(self):
print("Drink a lot of alcohol")#私有方法,方法前两个下划线,外部无法访问
def __show_psd(self):#私有方法
print(self.__psd) #内部可以访问,外部不可访问
m1=man()
print(m1.name)
继承
- 为了实现代码的重⽤,相同的代码不需要重复的编写;
- 定义:子类继承父类,子类就会拥有父类的方法和属性;子类可以有自己独特的方法属性;
- 语法:class 子类名(父类名): 如下:
python
复制代码
class animal: #父类,基类
def __init__(self):
self.name="tom"
def sleep(self):
print("%s can sleep" % self.name)
def eat(self):
print("%s can eat"% self.name)
class dog(animal): #dog类继承animal类,dog是子类,是派生类
def run(self):
print("can run")
d=dog()
d.sleep() #继承了父类的方法
d.eat() #继承了父类的方法
d.run() #子类自己的方法
- 父类可以有多个子类,但是子类只有一个父类;
- 父类下有子类,子类下还可以有子类,多级继承关系;
- 父类的私有属性和方法不能继承给子类;
方法重写
- 方法重写:子类继承父类的情况下才有方法重写;
- 两种方式
- 覆盖父类方法①,直接执行子类方法
- 扩展父类方法②,需要使用关键字super(),调用父类方法--即执行父类,再加扩展功能;
python
复制代码
#方法重写①覆盖父类方法;②扩展父类方法
class animal:
def __init__(self,name="tom"):
self.name=name
def sleep(self):
print("sleep")
def eat(self):
print("eat")
class dog(animal):
def sleep(self):
print("%s can sleep" % self.name) #和父类同名方法,覆盖父类方法①
def eat(self):
super().eat()# 在子类方法中调用父类的sleep方法,使用方法②
print("%s can eat" % self.name)
print("%s eat like meat" % self.name)
d=dog("哈士奇")
d.sleep() #直接执行子类的方法
d.eat() #既执行了父类的eat,又增加了功能
多态
- 不同的对象调⽤相同的⽅法,产⽣不同的执⾏结果;
- 不同的子类来自相同的一个父类,子类会覆盖父类的方法;
python
复制代码
class animal:
def __init__(self,name="animal"):
self.name=name
def eat(self):
print("%s can eat"%self.name)
class dog(animal):
def eat(self):
print("%s like eat meat" %self.name)
class cat(animal):
def eat(self):
print("%s like eat fish" % self.name)
d=dog("哈士奇")
d.eat() #执行相同的方法eat,产生不同的结果
c=cat("狸花猫")
c.eat()#执行相同的方法eat,产生不同的结果
其他
类属性和方法
- 类属性:定义在类里面,方法外面,定义的时候不需要self关键字,语法类似于定义普通变量;
- 类方法:
@classmethod关键字
- 类方法的一个参数是cls(不是self)
- 在类方法内部如果使用类属性,
cls.类属性名
- 类方法内部不能使用普通属性,也不能调用普通方法
- 因为类方法不需要对象的,但普通方法和普通属性一定需要通过对象调用
python
复制代码
class dog:
name = "哈士奇" # 如果在这个位置定义的变量,就是类属性,不用self关键字
@classmethod
def set_name(cls,name): #类方法:第一个参数是cls,
cls.name=name # 通过类方法的形参修改类属性name值
def __init__(self):
self.age=20 # 在类方法里面无法访问age
def test(self):
print("我是普通方法") # 在类方法中无法调用demo
#不用实例化
print(dog.name) # 显示类属性的值
dog.name = "狼狗" # 修改类属性的值
print(dog.name)
dog.set_name("藏獒") #通过类方法的形参修改类属性name值
print(dog.name)
静态方法
@staticmethod 静态方法不需要实例化为对象,通过类名.静态方法名 调用;
- 静态方法不能访问类中的其他成员;静态方法就是一个独立与类存在的函数;---与普通函数相似,相当于把普通方法放到类里面;
- 当代码量特别大的时候,函数也会特别多,为了避免函数的重名,可以把同名函数放到不同的类里面,做为静态方法;
python
复制代码
class dog:
@staticmethod
def test(): #静态方法
print("我是静态方法")
dog.test() #直接调用,不用实例化
object
- 类的顶级父类就是object,object类是python内部自带的;
- 你定义的所有的类都有父类
