面向对象编程与面向过程编程的差别:
面向过程编程:复杂的问题简单化,扩展性差。
面向对象编程:复杂读变高,扩展性强。
面向对象编程:
核心是对象二字,对象就是一个用来盛放数据与功能的容器
基于该思想编写程序就是创造一个个的容器
专门语法:
类
对象
属性查找
面向对象的三大特性:
封装:归类整合,把相关的数据跟功能封装在一起,很好的体现了扩展性强的特点
继承
多态
实例化:
调用类产生对象的过程称为实例化
调用类称为类的实例化
调用类的结果是一个对象,这个对象称为类的实例
面向对象编程思想
def tell_info(aaa):
print("my name is %s, my age is %s,my gender is %s" % (student["name"], student["age"], student["gender"]))
student = {
"name": "nana",
"age": 18,
"gender": "female",
"tell_info": tell_info} #学生对象,学生容器,self自己调自己的功能
student["tell_info"](student)
案例2:
类:用来存放相似数据,已经相似功能的容器,用来节省内存空间
def tell_info(aaa):
print("my name is %s, my age is %s,my gender is %s" % (student["name"], student["age"], student["gender"]))
student = {
"school": "清华大学",
"name": "nana",
"age": 18,
"gender": "female",
"tell_info": tell_info} # 学生对象,学生容器,self自己调自己的功能
student["tell_info"](student)
student1 = {
"school": "清华大学",
"name": "dada",
"age": 19,
"gender": "male",
"tell_info": tell_info} # 学生对象,学生容器,self自己调自己的功能
student["tell_info"](student1)
类与对象的关系图
类有两种属性:数据属性和函数属性
类与对象原理
定义类发生的事情
类与对象本质上都是名称空间,对象里面盛放字典独有类型的元素,类里面盛放相同类型的元素
类与函数的定义的差别,函数的名称空间只有在调用的时候才产生名称空间,类只要定义就会运行代码产生名称空间
类名:采用驼峰体
类与对象
对象是盛放相关的数据与功能的容器
类存放的是对象相似的数据与功能的容器
class Student:
school = "清华大学"
def tell_info(student):
print("my name is %s, my age is %s,my gender is %s" % (student["name"], student["age"], student["gender"]))
print("=====")
# print(Student.__dict__) #class就是在背后把Student的同类型元素做成了一个字典的模式,__dict__表示查看类里面的名称空间的元素
#调用类的底层逻辑
# 创造一个对象的字典格式,用来存放对象独有的数据
# 将对象与类建立好关联
obj1 = Student()
# print(obj1.__dict__) #建了一个空字典
# obj1.name = "nana" # obj1.__dict__["name"] = "nana"
# obj1.age = 18 # obj1.__dict__["age"] = 18
# obj1.gender = "female" # obj1.__dict__["gender"] = "female"
#
obj2 = Student()
# obj2.name = "dada" # obj2.__dict__["name"] = "dada"
# obj2.age = 19 # obj2.__dict__["age"] = 19
# obj2.gender = "male" # obj2.__dict__["gender"] = "male"
# 把对象写成函数
def init(self, x, y, z):
self.name = x
self.age = y
self.gender = z
init(obj1, "nana", 18, "female")
init(obj2, "dada", 19, "male")
print(obj1.__dict__)
print(obj2.__dict__)
print(Student.__dict__)
调用类的过程
class Student:
school = "清华大学"
def __init__(self, x, y, z): #Student.__init__(空对象,"nana", 18, "male")
self.name = x # 空对象.name="nana"
self.age = y # 空对象.age=18
self.gender = z # 空对象.gender="female"
def tell_info(student):
print("my name is %s, my age is %s,my gender is %s" % (student["name"], student["age"], student["gender"]))
调用类的过程
1.先创造一个空对象
2.自动触发类内的__init__函数的运行,将空对象当作第一个参数自动传入
3.返回一个初始化好的对象给obj1 #注意,obj1返回值是Student()的返回值,__init__规定不能有返回值
obj1 = Student("nana", 18, "female") # 返回值obj1={
"name"="nana","age"=18,"gender"="female"}
obj2 = Student("dada", 19, "male")
属性查找
对象.属性的查找顺序,优先从对象里面找,如果找不到会再从类里面找
# class Student:
# school = "清华大学"
#
# def __init__(self, x, y, z):
# self.name = x
# self.age = y
# self.gender = z
#
# def tell_info(student):
# print("my name is %s, my age is %s,my gender is %s" % (student.gender, student.age, student.gender))
#
#
# obj1 = Student("nana", 18, "female")
# obj2 = Student("dada", 19, "male")
#
# Student.tell_info(obj1)
# Student.tell_info(obj2)
# print(obj1.name) # obj1.__dict__["name"]
# print(obj1.school)
# 类.属性,从类自己的字典里面找,类内部传参,无法去全局名称空间里面找值,只能再类内部找,类内部找不到就报错
# print(Student.school) # 显示类里面school的值
# print(Student.__init__) # 函数Student.__init__的内存地址
# print(Student.tell_info) # 函数tell_info的内存地址
# 类中的数据属性是直接共享给所有对象用的
# 如果类的数据属性变了,那就所有数据的属性都改变,如果对象的数据属性改变了,那么只在该数据只在该对象内部发生改变
# obj1.school = "xxx"
# print(Student.school) # 清华大学
# print(obj2.school) # 清华大学
# print(obj1.school) # xxx
类中的函数属性
类中的函数可以直接调用,如果类来调用那么就是一个普通函数,按照函数的使用规则去使用就可以
但其实类中的函数时给对象用的,如果对象来调用那就是一个绑定方法,绑定方法会将调用者当作第一个参数传入
class Student:
school = "清华大学"
def __init__(self, x, y, z):
self.name = x
self.age = y
self.gender = z
def tell_info(student):
print("my name is %s, my age is %s,my gender is %s" % (student.gender, student.age, student.gender))
obj1 = Student("nana", 18, "female")
obj2 = Student("dada", 19, "male")
Student.tell_info(obj1)
Student.tell_info(obj2)
print(obj1.tell_info) #<bound method Student.tell_info of <__main__.Student object at 0x00EAE6D0>>
绑定方法的概念
类中定义的函数一般都至少需要一个参数的,该参数是往定义的函数里面自动传入对象的,这种绑定关系就是绑定方法
obj1.tell_info() #tell_info()会将调用者当作第一个参数传入,如果函数中还有其他参数,那么继续传其他的参数
obj2.tell_info()
隐藏属性
__开头的属性的特点:
并没有真的藏起来,只是变形的
**该变形只在类定义阶段,扫描语法的时候执行,此后__开头的属性都不会变形
该隐藏对外不对内
class People:
# __country = "China" # 将一个属性加了__开头就代表把该属性隐藏了
def __init__(self, name, age):
self.__name = name # {
'_People__name': 'nana'}
self.__age = age # '_People__age': 18
def __func(self): # _People__func
print("xx")
def tell_name(self):
print(self.__name) # {
'_People__name': 'nana'}
# self["__name"]
obj1 = People("nana", 18)
obj1.tell_name()
print(People.__country) #加了__显示没有该属性
print(People.__dict__) #__country显示结果:'_People__country': 'China'
print(People._People__country)
print(obj1.__dict__)
obj1.__gender = "female"
print(obj1.__gender) # 可以直接访问到,female
obj1.tell_name() # 对外不对内
为何要影藏属性
1.隐藏数据属性为了严格控制类外部访问者对属性的操作
class People:
def __init__(self, name, age):
self.__name = name # _People__name
self.__age = age # _People__age
def tell_info(self): #通过改接口的方式让用户只能查看
print(self.__name, self.__age)
def set_info(self, name, age): #通过调用函数改接口的的方式控制用户对属性的更改
if type(name) is not str:
print("名字必须是字符串")
return
if type(age) is not int:
print("年龄必须是数字")
return
self.__name = name
self.__age = age
obj1 = People("nana", 18)
# obj1.tell_info()
obj1.set_info("NANA", 18)
obj1.tell_info()
2.隐藏函数(功能)属性为了隔离复杂度
class ATM:
def __card(self):
print("插卡")
def __auth(self):
print("用户认证")
def __input(self):
print("取出")
def withdraw(self):
self.__card()
self.__auth()
self.__input()
a = ATM()
a.withdraw()