一、== 调用函数和调用结果 ==的区别(面试题)
1.调用函数、递归函数
里面放的是函数
def hello():
def aaa(j):
def bbb():
return j**j
return bbb()
f = []
for i in range(1,4):
f.append(aaa(i)) #调用函数aaa(i),实际返回的是j**j,循环的时候已经马上调用了,往里面放的是函数的结果,而不是本身
return f
f1,f2,f3 = hello() #返回一个列表,里面填的是返回的3个值
print(f1,f2,f3)
结果:1 4 27
2.调用结果
里面放的是结果
def world():
f = []
for i in range(1,4):
def aaa():
return i*i
f.append(aaa) #aaa只是个变量名,指向函数本体,没有调用
return f
print(world()) #只知道里面有3个函数,但是它并不关心函数里面到底是什么东西,等调用的时候,才会分析函数里面是什么?等它关心的时候,i已经是3了
f1,f2,f3 = world() #调用的时候i已经是3了,到最后计算出为9,
print(f1(),f2(),f3()) #调用的为最后计算的9
结果:9 9 9
二、lambda匿名函数(代码不需要重复调用和代码封装的时候用)
== 优点 :代码不需要重复调用和代码封装的时候用 ==
#方法一
hello = lambda x,y:x+y #赋给一个变量进行调用,匿名函数可以减少函数名的冲突
print(hello(4,8))
结果:12
#方法二
def hello(x,y):
return x+y
print(hello(4,8))
结果:12
#方法三
def hello(x,y):
return x+y
from functools import reduce
result = reduce(hello,range(10))
print(result)
结果:45
三、高级函数
reduce
map
sorted
filter
1.sorted
排序(默认reverse=False正序)
lists = [3,2,1,5,32,6,7,43,4,346]
print(sorted(lists)) #sorted相当于创建了一个新的值,直接打印就行了
结果:[1, 2, 3, 4, 5, 6, 7, 32, 43, 346]
lists = [3,2,1,5,32,6,7,43,4,346]
lists.sort() #sort改变了之前的值,打印原来的值就行了
print(lists)
结果:[1, 2, 3, 4, 5, 6, 7, 32, 43, 346]
倒序
lists = [3,2,1,5,32,6,7,43,4,346]
lists.sort(reverse=True) #sort改变了之前的值,打印原来的值就行了
print(lists)
结果:[346, 43, 32, 7, 6, 5, 4, 3, 2, 1]
正序(默认reverse=False)
lists = [3,2,1,5,32,6,7,43,4,346]
lists.sort(reverse=False) #sort改变了之前的值,打印原来的值就行了
print(lists)
结果:[1, 2, 3, 4, 5, 6, 7, 32, 43, 346]
2.filter
1~100的奇数
odd_number = lambda x:x%2==1
print(list(filter(even_number,range(1,101))))
1~100的偶数
even_number = lambda x:x%2==0
print(list(filter(even_number,range(1,101))))
3.根据hello1后边的数字排序(非常常见的面试题)
dicts = {'hello1':'1','hello2':'5','hello3':'6','hello4':'8','hello5':'7'}
排完之后变成这样
dict2 = {'hello1': '1', 'hello2': '5', 'hello3': '6', 'hello5': '7', 'hello4': '8'}
方法一
dicts = {'hello1':'1','hello2':'5','hello3':'6','hello4':'8','hello5':'7'}
print(dict(sorted(dicts.items(),key=lambda x:x[1])))
#x[1]填1根据'hello1':'1'后面排序,填0根据前面排序, x:x[1]传进来的x接的是什么样的参数?
[('hello1':'1'),('hello2':'5')] 接的x实际上是('hello2':'5'),就是里面的元组
实际上就是给里面的元组排序,最后还要重新转成dict
结果:{'hello1': '1', 'hello2': '5', 'hello3': '6', 'hello5': '7', 'hello4': '8'}
方法二
dicts = {'hello1':'1','hello2':'5','hello3':'6','hello4':'8','hello5':'7'}
dict1 = {}
dict2 = {}
for a,b in dicts.items():
dict1.update({b:a}) #先交换'hello1': '1'键和值
for i in sorted(dict1): #sorted实际上是根据键排序,但是已经键和值交换了
dict2.update({dict1[i]:i}) #然后拍完顺序再交换过来
print(dict2)
结果:{'hello1': '1', 'hello2': '5', 'hello3': '6', 'hello5': '7', 'hello4': '8'}
四、面向对象
(1)类
包含属性(静态)
和方法(动态)
(2)实例化:根据类生成对象的过程
实例:具体到实体上
化:根据类生成实例
1.类class
class Student: #类
# 构造方法,当进行实例化的时候,会触发构造方法,本质上是一个函数,根据类Student()生成实例stu1的时候,会触发
def __init__(self,name,score):
#对象属性、实例属性
self.name = name #对象属性绑定,这儿的self对象等价于stu1、stu2
self.score = score
# 方法
def show_score(self):
print(self.score)
#实例化
stu1 = Student('杜甫','45')
print(stu1.name,stu1.score)
stu1.show_score() #调用方法
stu2 = Student('孟浩然','45')
print(stu2.name,stu2.score)
stu2.show_score() #调用方法
print(id(stu1),id(stu2)) #内存空间里面的数是完全不一样的,证明他们两个是完全独立的个体
结果:
杜甫 45
45
孟浩然 45
45
2949296619088 2949296614384
2.基类、父类class Student(object),object
class Student(object): #类
# 构造方法,当进行实例化的时候,会触发构造方法,本质上是一个函数,根据类Student()生成实例stu1的时候,会触发
def __init__(self,name,score):
#对象属性、实例属性
self.name = name #对象属性绑定,这儿的self对象等价于stu1、stu2
self.score = score
# 方法
def show_score(self):
print(self.score)
#实例化
stu1 = Student('杜甫','45')
print(stu1.name,stu1.score)
stu1.show_score() #调用方法
stu2 = Student('孟浩然','45')
print(stu2.name,stu2.score)
stu2.show_score() #调用方法
print(id(stu1),id(stu2)) #内存空间里面的数是完全不一样的,证明他们两个是完全独立的个体
结果:
杜甫 45
45
孟浩然 45
45
1506655075872 1506655071744
3.基类、父类
(1)
class Animal(object):
def eat(self):
print('i like food!')
class Dog(Animal): #让Dog继承Animal类
def eat(self):
print('i like meat!')
class Cat(Animal): #让Cat继承Animal类
def eat(self):
print('i like fish!')
dog1 = Dog() #实例化
dog1.eat() #调用Dog里面的eat()方法
#结果:i like meat!
cat1 = Cat() #实例化
cat1.eat() #调用Cat里面的eat()方法
#结果:i like fish!
(2)类的继承
上面结果显示父类eat方法并没有什么效果,我们给他改一下。
类的继承
class Animal(object):#object就是父类的父类,也就是祖宗,所有的类都要继承一个基类,什么都不写相当于默认object,所以说object是所有类的基类
def eat(self):
print('i like food!')
class Dog(Animal): #让Dog继承Animal类
def eat1(self):
print('i like meat!')
class Cat(Animal): #让Cat继承Animal类
def eat2(self):
print('i like fish!')
dog1 = Dog() #实例化
dog1.eat() #调用Dog里面的eat()方法,里面已经没有eat()方法了
#结果:i like food!
cat1 = Cat() #实例化
cat1.eat() #调用Cat里面的eat()方法,里面已经没有eat()方法了
#结果:i like food!
#实例化一个子类,当调用子类方法的时候,如果子类里面有方法,就用子类的,没有就会继承父类的方法,所以结果都是i like food!
4.Python多类继承
动物类,哺乳动物,飞,跑,在Python中,多重继承就是允许子类继承多个父类,子类可以调用多个父类的方法和属性。
但是,当多个父类拥有相同方法名的方法时,我们通过方法名调用父类方法就有一定的顺序。
class Animal(object):
def eat(self):
print('i like food!')
class Runnable(object):
def run(self):
print('i can run!')
class Flyable(object):
def fly(self):
print('i can fly!')
class Mammal(object): #哺乳动物
def show_type(self):
print('i am Mammal!')
class Ovipara (object): #卵生
def show_type(self):
print('i am Ovipara')
class Dog(Animal,Runnable,Mammal): #dog继承了Animal,Runnable,Mammal
def eat1(self):
print('i like meat')
class Cat(Animal):
def eat(self):
print('i like fish')
dog1 = Dog() #实例化dog
dog1.eat() #所以用父类的eat()方法
dog1.run()
dog1.show_type()
#结果:dog有了3个父类
# i like food!
# i can run!
# i am Mammal!
5.做题:定义一个学生类,看学生成绩有没有几个,是优良还是什么?
面向对象的三大特性:继承、封装、多态
class Student:
# 构造函数
def __init__(self,name,score):
# self是对象
# 对象属性,实例属性
self.name = name
self.score = score
def show_level(self):
level = '优' if self.score>90 else '良' if self.score>80 and self.score<=90 else '及格' if self.score>60 and self.score<=80 else '不及格'
return level
stu1 = Student('柳宗元',100) #实例化
stu1.score = 40 #修改了stu1的分数,不想改怎么办?
print(stu1.score)
print(stu1.show_level()) #调用方法
stu2 = Student('孟浩然',19)
print(stu2.show_level())
# 结果:
# 40
# 不及格
# 不及格
6.私有属性(属性不想被修改)
Python的面向对象开发过程中,对象的某些属性只想在对象的内部被使用,但不想在外部被访问到这些属性。
即:私有属性是对象不愿意公开的属性。私有属性不安全。
修改了stu1的分数,不想改怎么办?
(1)加两个杠
self.name = name和self.score = score、self.score>90加__变成self.__score、self.__name
class Student:
# 构造函数
def __init__(self,name,score):
# self是对象
# 对象属性,实例属性
self.__name = name
self.__score = score
def show_level(self):
level = '优' if self.__score>90 else '良' if self.__score>80 and self.__score<=90 else '及格' if self.__score>60 and self.__score<=80 else '不及格'
return level
stu1 = Student('柳宗元',100) #实例化
stu1.__score = 40 #这里的stu1.__score = 40相当于创建了一个新的,跟里面的__score不是一个东西
print(stu1.__score)
print(stu1.show_level()) #调用方法
结果:
40
优
写了self.__score,对外界来说相当于把属性值隐藏起来了
(2)相当于创建了一个新的,跟里面的__name不是一个名字,那在外部新建的是什么名字呢?
class Student:
# 构造函数
def __init__(self,name,score):
# self是对象
# 对象属性,实例属性
self.__name = name
self.__score = score
def show_level(self):
level = '优' if self.__score>90 else '良' if self.__score>80 and self.__score<=90 else '及格' if self.__score>60 and self.__score<=80 else '不及格'
return level
stu1 = Student('柳宗元',100) #实例化
print(stu1._Student__name) #在外部改一个名字,名字就是_Student__name
stu1._Student__score = 65
print(stu1.show_level())
(3)加一个杠(不希望被外部调用)
7.模块
(1)类属性
class Student:
# 类属性
num = 0
# 构造函数
def __init__(self,name,score):
# self是对象
# 对象属性,实例属性
self.__name = name
self.__score = score
def show_level(self):
level = '优' if self.__score>90 else '良' if self.__score>80 and self.__score<=90 else '及格' if self.__score>60 and self.__score<=80 else '不及格'
return level
stu1 = Student('孟浩然',100)
print(stu1._Student__name) #用stu1实例调用了实例的一个_Student__name
print(Student._Student__name) #能不能被类名调用?报错,类没有这个属性
print(Student.num) #结果是1,类属性是直接可以被类调用的
print(stu1.num) #结果是1,类属性也可以被实例对象调用的
(2)每调用一次,类属性+1
把存储放到外边,触发事件放到构造函数里面
class Student:
# 类属性
num = 0 #把存储放到外边,触发事件放到构造函数里面
# 构造函数
def __init__(self,name,score):
# self是对象
# 对象属性,实例属性
self.__name = name
self.__score = score
Student.num+=1 #函数调用一次,类属性+1
def show_level(self):
level = '优' if self.__score>90 else '良' if self.__score>80 and self.__score<=90 else '及格' if self.__score>60 and self.__score<=80 else '不及格'
return level
stu1 = Student('孟浩然',100)
print(stu1.num)
stu1 = Student('王安石',98)
print(stu1.num)
结果:
1
2