面向对象基础

面向过程编程

关键在于过程

过程指的是,先干啥 再干啥 最后干啥,设计思想好比一条流水线
注意:面向过程与函数编程是完全不同的
优点:将复杂的问题流程化,简单化
缺点:由于代码严格按照流程编写,导致扩展性极差
-----------------------------------
#面共对象对比面向过程
#使用面向对象来编写程序时,不去思考具体的实现步骤,重点是什么样的对象可以完成这个事情
面向过程想的是:怎么做
面向对象想的是:谁来做

优点:扩展性高,修改单独某一个对象,不会影响其他对象灵活度,复用性,降低耦合度
缺点:1、相对于面向过程而言,编程的复杂度提高了
   2、无法准确预知执行结果

  使用场景:对扩展性要求较高的应用程序(面向用户的应用程序扩展性较高)
View Code

 

 

一、面向对象简介

#什么是面向对象
    是一种编程思想
    关键在于对象,
#什么是对象:一系列特征和技能的结合体

------------------------------------------------------
1、使用面型对象开发,第一步是设计 类
2、使用  类名()  创建对象,创建对象的动作有两步:
           1)在内存中为对象分配空间
           2)调用初始化方法__init__ 为对象初始化

3、对象创建后,内存中就有了一个对象的  实实在在 的存在--实例


因此,通常会把:
1、创建出来的  对象 叫做 类的实例
2、创建对象的 动作 叫做实例化
3、对象的属性叫做实例属性
4、对象的调用方法叫做实例方法

在程序执行时

1、对象各自拥有自己的 实例属性
2、调用对象方法,可以通过self.
        访问自己的属性
        调用自己的方法

结论
·每一个对象  都有自己 独立的内存空间 ,保存各自不同的属性
·多个对象的方法,在内存中只有一份,在调用方法时,需要把对象的引用 传递到方法的内部
面向对象简介

 

 

二、类与对象基础

 

#2.1类和对象的关系
    生活中:先有对象,再有类  (先有人,再有人类)
    程序中:先有类,再由类产生对象  (先定义需求,再产生对象


#2.2什么是类
    类是一系列相同特征(变量)与技能(函数)的对象的结合体,即类体中最常见的就是变量和函数的定义


#2.3类的本质
    类体代码会在类定义阶段立即执行,会产生一个类的名称空间,用来将类体代码执行过程中产生的名字都丢进去
    本质:是一个名称空间,或者说是一个用来存放变量与函数的的容器


#2.4类的用途
    类的用途之一:当做名称空间从内部取出名字来使用
    类的用途之二:调用类来产生对象

 

 

 

 三、对象传值的两种方式

class Student:

    def choose_course(self):
        pass

stu1=Student()
 
stu1.name = 'pdun'           #对象.
stu1.age = 1
stu1.sex = 'man'
View Code

 

#__init__的功能:是在实例化时就为对象初始自己独有的特征
#注意:不能有返回值


class Student:
    def __init__(self,name, age, sex):
        self.name = name
        self.age = age
        self.sex = sex
stu =Student('pdun',1,'man')
init

 

 

 

类方法

#类方法可以直接被类调用,不需要对象
#当一个方法只涉及改变静态属性(类中的变量)时,应考虑用@classmethod
class Goods():
    price=10
    @classmethod

    def new_price(cls,new_price):
        cls.price=new_price
        print(cls.price)

Goods.new_price(5)
obj = Goods()
print(obj.price)
View Code

 静态方法

#在完全面向对象编程中,如果一个函数,既和对象没有关系,也与类没有关系,就用staticmethod把它变成静态方法,使用时直接    对象.该方法
class Static():

    @staticmethod
    def login():
        user = input('用户名:')
        pwd = input('密码:')
        print(user,pwd)

Static.login()
View Code
#总结
1、类方法和静态方法都是类调用的
2、对象可以调用静态方法和类方法吗?  可以,但一般推荐类调用
3、静态方法没有参数,它就相当于一个普通的函数,只不过在调用的时候多加一个类名罢了,它相当于普通函数,当然可以传参

 

 

 元类

#exec:三个参数

#参数一:包含一系列python代码的字符串

#参数二:全局作用域(字典形式),如果不指定,默认为globals()

#参数三:局部作用域(字典形式),如果不指定,默认为locals()

#可以把exec命令的执行当成是一个函数的执行,会将执行期间产生的名字存放于局部名称空间中

例如
class_dic = {}
exec("x=1",{},class_dic)
print(class_dic)
>>{'x': 1}
会把x=1执行时产生的名称空间放到class_dic中
如果在执行代码时需要用到全局的名称空间,就到参数二中找
#拿到类名
class_name = "OldBoy"

#拿到类的基类们
class_bases = (object,)

#执行函数体代码,拿到名称空间
class_dic = {}

x = """
school = "oldboy"
def __init__(self,name,age):
    self.name = name
    self.age = age
def score(self):
    print("name is %s" % self.name)
"""
exec(x,{},class_dic)   #执行代码,将所产生的名称空间放到class_dic中
print(class_dic)
OldBoy = type(class_name,class_bases,class_dic)  #调用元类得到类
class关键字底层工作原理

 

#!!但凡继承了type的类,才称之为元类,否则只是普通的类!!
class Mymetaclass(type):
    def __init__(self,class_name,class_bases,class_dic):
        print(self)
        print(class_name)
        print(class_bases)
        print(class_dic)
class OldBoy(metaclass=Mymetaclass):
    a = 1
    def __init__(self,name):
        self.name = name

------------------------------------------------------
#错误的
class Mymetaclass(type):
    def __init__(self):     #错误在此处
        print(self)
class OldBoy(metaclass=Mymetaclass):
    a = 1
    def __init__(self,name):
        self.name = name

>>TypeError: __init__() takes 1 positional argument but 4 were given

#说明底层原理是
#OldBoy = Mymetaclass(OldBoy ,class_bases,class_dic)
#需要把自身,类名,类的基类,所产生的名称空间一起传给元类

 自定义元类控制类的产生

自定义元类可以控制类的产生过程,类的产生过程其实就是元类的调用过程,
即OldboyTeacher=Mymeta('OldboyTeacher',(object),{...}),
调用Mymeta会先产生一个空对象OldoyTeacher,
然后连同调用Mymeta括号内的参数一同传给Mymeta下的__init__方法,完成初始化,于是我们可以
class Mymeta(type): #只有继承了type类才能称之为一个元类,否则就是一个普通的自定义类
    def __init__(self,class_name,class_bases,class_dic):
        # print(self) #<class '__main__.OldboyTeacher'>
        # print(class_bases) #(<class 'object'>,)
        # print(class_dic) #{'__module__': '__main__', '__qualname__': 'OldboyTeacher', 'school': 'oldboy', '__init__': <function OldboyTeacher.__init__ at 0x102b95ae8>, 'say': <function OldboyTeacher.say at 0x10621c6a8>}
        super(Mymeta, self).__init__(class_name, class_bases, class_dic)  # 重用父类的功能

        if class_name.islower():
            raise TypeError('类名%s请修改为驼峰体' %class_name)

        if '__doc__' not in class_dic or len(class_dic['__doc__'].strip(' \n')) == 0:
            raise TypeError('类中必须有文档注释,并且文档注释不能为空')

class OldboyTeacher(object,metaclass=Mymeta): # OldboyTeacher=Mymeta('OldboyTeacher',(object),{...})
    """
    类OldboyTeacher的文档注释
    """
    school='oldboy'

    def __init__(self,name,age):
        self.name=name
        self.age=age

    def say(self):
        print('%s says welcome to the oldboy to learn Python' %self.name)
自定义元类控制类的产生

 

 自定义元类控制类的调用

 

    

    

 

    

posted @ 2019-02-18 17:09  pdun  阅读(196)  评论(0编辑  收藏  举报