面向对象编程 类 后补充了元类 和单例

1.面向过程编程(概念:)
核心是"过程"二字,过程指的是解决问题的步骤,即先干什么再干什么
基于该思想编写程序就好比在编写一条了流水线,是一种机械式的思维方式

优点:复杂的问题流程化,进而简单化

缺点:可扩展性差 现今社会客户的需求千变万化 对扩展性要求较高‘

使用场景:不需要扩展 或者是随扩展性要求不高,例如:linux内核,shell,
脚本

案例:工厂流水线

面向过程中我们关注的点,完成这个任务 具体的步骤 一步一步去完成

2.面向对象:
也是一种编程思想,什么是对象(在现实生活中实实在在存在的,具备自己特
征和行为的事物,反过来说 对象就是特征和技能的结合体)

如何来区分,如果能够精确的找到一个十五,他就是一个对象

核心"对象"二字,对象指的是特征与技能的结合体

基于该思想编写程序就好比在创造一个世界,你就是这个世界的上帝,是一
种上帝式的思维逻辑

优点:可扩展性强

缺点:编程的复杂度高于面向过程

面向对象编程:我们关注的点是,使用什么样的对象可以完成我的任务
例如:把大象装进冰箱,什么样的对象可以帮我完成这个任务;只要找到这个
这个对象,命令它来做事情,你从一个操作者 ,例如:西游记中如来完成传经的任务,
所以找了唐僧几个对象来完成

优点:1.对于指挥者(程序员)来说 不需要再关心具体的步骤
2.扩展性,一个单独的个体的特征或者行为发生变化时 不会影响他人

缺点:1.程序的复杂度变高,你首先需要设计出这些对象。注意:要避免一个过度设计
的问题
2.对程序的执行结果的可控性降低











3.类与对象:

类就是分类 类型的意思
定义:一堆具备相同特征和行为的事物的抽像概念,不实际存在的

生活中:类怎么来的,是通过对象特征和行为抽取而来的,所以先要有对象再有类

编程中:必须要先有类,才能有对象,因为你必须先告诉程序,你这个对象有什么样的特征
和行为

类的作用:用于描述该类的对象具备什么样的特征和行为


4.python中的类
类的定义及其使用
#yufa :class关键字 类名
#类名规范 大写开头 驼峰命名法
class SH01dboyStudent:
#描述该类对象的特征
school="上海01dboy"
name="agon"
age=18
gender="unlnow"
#在定义阶段
#只要包含该类的py文件被执行 首先创建类的名称空间
#执行代码 将产生的名臣俄国放入名称空间
print("=============")

#描述该类对象的行为 通过函数
def say_hi(self):
print("hello oldBoy")


#使用类中的属性
print(SH01dboyStudent.__dict__)
print(SH01dboyStudent.name)
#使用类中的函数
print(SH01dboyStudent.say_hi)
#使用类直接调用类中的函数时 与嗲用普通函数没有任何取别 self仅
#仅是位置参数
SH01dboyStudent.say_hi(10)


5.创建对象和对象属性
对象中不许有一个指向类的名称空间的地址(如果自己里有 就拿自己的 没有就去找类中的)

#创建对象
#语法在类名后加括号 与调用函数写法相同
stu= SH01dboyStudent()
#访问对象属性
print(stu.school)
print(SH01dboyStudent.school)
#修改属性值
stu.school="北京01dboy"
print(stu.school)
#增加属性
stu.room_num=1008
print(stu.room_num)
#删除属性
del stu.room_num
print(stu.room_num)

#对象与类的名称空间是独立的
stu.school="北京01dboy"
stu.room_num=1008
print(stu.__dict__)
print(SH01dboyStudent.__dict__)

#如果对象的属性是相同的就应该放到类中 作为一个公共的数据
stu.school

#对象的属性查找顺序
#对象自己的名称空间==>类的名称空间
syul=SH01dboyStudent()
syul.school="深圳01dboy"
print(syul.school)
print(syul.__dict__)


class Dog:
#作为一只狗 应该有昵称 age color gender
#但是不能写到类中 因为每个狗是不一样的


#__init__称之为初始化函数 它会在创建对象的时候自动执行
#创建对象时
#1.创建一个空对象
#2.执行__init__函数 并且自动传入了这个对象

#该函数的作用,就是为对象的属性赋初始值
def __init__(self,name,color,age,gender):
print("狗的颜色__init__执行了")
print(a,b,)
print(self)
self.name=name

pass
dog1=Dog()
print(dog1)
dog1.name="大黄"
dog1.age="1"

dog2=Dog()
print(dog2)
dog2.name="二哈"
dog2.age="2"

#在创建对象时,传入参数
#类内部定义的函数 其实是给对象使用的 而且是绑定给对象用 绑定给不同的对象就是不同的绑定方法
dog1=Dog("大黄","黄色",2,"female")
print(dog1.__dict__)
#绑定方法的特殊之处在于,谁来调用 就会将随当作第一个阐述自动传入
dog2=Dog("二哈","白色",1,"female")
print(Dog(dog2))


#1.使用场景 需要为每一个对象定制不同的属性值
#2.__init__在创建对象后自动执行
#3.第一个self参数 指的是这个对象本身 不需要手动传值

#类的调用
Dog.sheep(10)
#对象调用
dog1.sheep()
#对于类而言 sleep就是一个普通函数
#对对象而言 sleep就是一个绑定方法
#绑定方法是什么’
#是对象与类中的某个函数的绑定关系 就像生活中 我们都会吃饭 你吃了我不会饱 不同的对象绑定关系的方式也不同
#问什么要把函数进行绑定 因为对象的行为通常都需要访问或修改这个对象的数据,如果没有对象直接调用函数是没
# 有意义的 在函数中是访问不到对象的数据 所以将函数和对象进行了绑定

#在使用绑定方法时 不需要关心self参数 会自动将这个对象进行传参





补充&修改:

上节课复习:
1.什么是面向对象编程:
是一种编程思想,核心是对象二字,对象是特征与技能的结合体,基
于该思想编写程序,就好比创造一个世界,世界是又一个个具体存在
的对象组成的,你就是这个世界的上帝,这一种上帝式的思维方式。
优点:扩展性强
缺点:编程的复杂度要高与面向过程

2.类:
对象是特征和技能的结合体,类则是一系列对象相同的特征与技能的
结合体
在现实世界中,先有一个个具体存在的对象,然后随着人类文明发展
总结出的类
在程序中一定先定义类,先调用类来产生对象


面向对象是相对于面向过程更高程度的一种封装

3.老男孩选课系统:
在现实世界中具体存在的对象:
对象一:
特征:
姓名="周铁蛋"
年龄="38"
性别="男"
学校="01dboy"
技能:
选课

对象二:
特征:
姓名="美男子"
年龄="18"
性别="男"
学校="01dboy"
技能:
选课

对象三:
特征:
姓名="张铜蛋"
年龄="38"
性别="女"
学校="01dboy"
技能:
选课

对象四:
特征:
姓名="egon"
年龄="18"
性别="男"
学校="01dboy"
等级=10
技能:
打分
在现实世界中老男孩学生类
相似的特征
学校="01dboy"
相似的技能
选课



class O1dboyStudent:
#相似的特征
school="O1dboy"

def __init__(self,name, age, gender):
obj.name = name
obj.age = age
obj.gender = gender
#相似的技能
def choose_course(self):
print("is choosing course")
print("=================")

#类的用途:
#用途一:类的本质就是一个名称空间,可以对该名称空间进行增删改查
#用途二:调用类来产生对象
#1.会产生一个空对象obj
#2.会触发类中__init__方法,O1dboyStudent。__init__(obj)
stu1=O1dboyStudent("周铁蛋","38","male")
stu2=O1dboyStudent()
stu3=O1dboyStudent()
"""
stu1.name="周铁蛋"
stu1.age="38"
stu1.gender="male"
print(stu1.__dict__)

stu2.name="美男子"
stu2.age="18"
stu2.gender="male"
print(stu2.__dict__)

stu3.name="张铜蛋"
stu3.age="18"
stu3.gender="female"
print(stu3.__dict__)
"""
# def inie(obj,name,age,gender):
# obj.name=name
# obj.age=age
# obj.gender=gender
# init(stu1,"周铁蛋","38","male")

#一切皆对象
#在python中统一了类与类型的概念
class Foo():
pass
obj=Foo()
print(type(obj))
l=list([1,2,3])
#print(type(l))
print(l)
l.append(4)#
list.append(1,4)
print(l)
#绑定方法:
#在创建对象时,传入参数
#类内部定义的函数 其实是给对象使用的 而且是绑定给对象用 绑定给不同的对象就是不同的绑定方法
dog1=Dog("大黄","黄色",2,"female")
print(dog1.__dict__)
#绑定方法的特殊之处在于,谁来调用 就会将谁当作第一个参数自动传入
dog2=Dog("二哈","白色",1,"female")
print(Dog(dog2))


#1.使用场景 需要为每一个对象定制不同的属性值
#2.__init__在创建对象后自动执行
#3.第一个self参数 指的是这个对象本身 不需要手动传值

#类的调用
Dog.sheep(10)
#对象调用
dog1.sheep()
#对于类而言 sleep就是一个普通函数
#对对象而言 sleep就是一个绑定方法
#绑定方法是什么’
#是对象与类中的某个函数的绑定关系 就像生活中 我们都会吃饭 你吃了我不会饱 不同的对象绑定关系的方式也不同
#问什么要把函数进行绑定 因为对象的行为通常都需要访问或修改这个对象的数据,如果没有对象直接调用函数是没
# 有意义的 在函数中是访问不到对象的数据 所以将函数和对象进行了绑定

#在使用绑定方法时 不需要关心self参数 会自动将这个对象进行传参

2. 元类:
元类是什么?
本质导航也是一个类,元类是用于实例化其他类
一切皆对象,类也是对象 在使用上与函数对象无区别

用于创建类的类 叫做元类 都是type
主要控制类的创建__init__ 类的实例化__call__

一个类必须具备的内容
1.类名
2.基类
3.名称空间

通过查看__class__ 可以看到我们定义的类是由type类实例化得来的

class_name = "Dog"
bases = (object,)
pic_dict = {}
class_body = """
def __init__(self):
print("xxxxx1")
color="red"
def talk(self):
print("iiiiii4")
print(self.color)
return
"""
exec(class_body, {}, pic_dict)
# print(pic_dict)
c = type(class_name, bases, pic_dict)
p1=c()
print(p1.talk())


在默认情况下 所有的类都是通过type这个元类实例化的
我们完全可以自己来实例化
元类的作用?
用于创建类的类,称之为元类

举例:
class MyMetaclass(type):
#什么时候执行?MyMetaclass 定义一个类是系统会自动去调用元类的
def __init__(cls,class_name,bases,namepace):
#既然创建类时 会自动执行该方法 那么完全可以编写些逻辑在init中来控制类的创建
if not class_name.istitle():
raise TypeError("类名首字母需要大写!")
if object not in bases:
raise TypeError("需要显式继承object类")
print(cls)
print(class_name)
print(bases)
print(namepace)
# 当解释器执行到这一行diamante时 自动调用了MyMetaclass
class Foo(object,metaclass=MyMetaclass):#等同于Foo=MyMetaclass()
attr=123
pass



class Bar:
def __call__(self,*args,**kwargs):
print("run call")
b1=Bar()
# 在调用对象的时候自动触发执行__call__
b1()
# 推到理论 b1是Bar的实例 调用b1 会触发Bar中的__call__
#Bar 是type的实例 调用Bar 应当触发type中的__call__


class MyMetaClass(type):
def __call__(self, *args, **kwargs):
# 做一个假需求:判断实例化参数是字符串类型
#isinstance(args[0],str)
if type(args[0])==str:
raise TypeError("名字必须是字符串")
print("12345678")
# 建立一个self的空对象
# 这是自定义元类时 必须要有的模板 以保证可以正常实例化产生对象
obj=object.__new__(self)
obj.__init__(*args, **kwargs)
return obj

class Foo(metaclass=MyMetaClass):
def __init__(self,name):
print(name)
pass
# 调用类 本质就是在调用__call__其返回值表示实例化得到的对象
res=Foo(1)
print(res)
#调用一个类 创建一个空对象,调用__init__来完成对象的初始化,返回该对象

#总结:
#控制类的调用 也就是实例化过程 核心函数元类中的__call__
#需要注意的是,在__call__中应当先完成基础的逻辑 1.创建空对象 2.执行__init__
#3.返回该对象
#在此基础上添加额外的业务逻辑




#单例模式:
#是一种设计模式 是设计模式中比较简单的一种
#指的是 一个类有且仅有一个实例 就叫做单例

#实现单例 就通过判断是否已经创建过对象

# 为什么要使用单例这种模式
#之前在创建对象时 每个对象中的数据不相同 对象实际上数据和处理数据的方法的结合体
#当对象中的数据是相同的 共享的时候 使用单例

#例子
# u1=user("张三",29,"man")
# u2=user("张三",29,"man")
# u3=user("张三",29,"man")
# 可以改写成u3=u2=u1,数据


# 元类实现单例 就是拦截了元类中的__call__的正常执行 使得创建对象都必须经过自己判断的逻辑
# 类中的__init__也被拦截了。



# 很重要的单例模式举例:
class MyMetaClass(type):
instance=None
def __call__(cls, *args, **kwargs):
if not MyMetaClass.instance:
#创建一个空对象
MyMetaClass.instance=object.__new__(cls)
print("创建了新的播放器!")
#初始化对象
MyMetaClass.instance.__init__(*args, **kwargs)
#返回该对象
return MyMetaClass.instance

# 只能由一个播放器实例
class CDPlayer(metaclass=MyMetaClass):
def play(self,music):
print("切换音乐",music)
def __init__(self,music_name):
self.music_name=music_name
#两次实例化对象p1和p2 都是一个
p2=CDPlayer('往后余生!908')
p1=CDPlayer('往后余生!')
p1.play('往后余生!')
p2.play("二十五点")
p1.play('离人愁!')



2. 元类:
元类是什么?
本质导航也是一个类,元类是用于实例化其他类
一切皆对象,类也是对象 在使用上与函数对象无区别

一个类必须具备的内容
1.类名
2.基类
3.名称空间

通过查看__class__ 可以看到我们定义的类是由type类实例化得来的

class_name = "Dog"
bases = (object,)
pic_dict = {}
class_body = """
def __init__(self):
print("xxxxx1")
color="red"
def talk(self):
print("iiiiii4")
print(self.color)
return
"""
exec(class_body, {}, pic_dict)
# print(pic_dict)
c = type(class_name, bases, pic_dict)
p1=c()
print(p1.talk())


在默认情况下 所有的类都是通过type这个元类实例化的
我们完全可以自己来实例化
元类的作用?
用于创建类的类,称之为元类

举例:
class MyMetaclass(type):
#什么时候执行?MyMetaclass 定义一个类是系统会自动去调用元类的
def __init__(cls,class_name,bases,namepace):
#既然创建类时 会自动执行该方法 那么完全可以编写些逻辑在init中来控制类的创建
if not class_name.istitle():
raise TypeError("类名首字母需要大写!")
if object not in bases:
raise TypeError("需要显式继承object类")
print(cls)
print(class_name)
print(bases)
print(namepace)
# 当解释器执行到这一行diamante时 自动调用了MyMetaclass
class Foo(object,metaclass=MyMetaclass):#等同于Foo=MyMetaclass()
attr=123
pass














原文地址:https://www.cnblogs.com/yanhui1995/p/9829611.html