python面向对象

面向对象的相关知识

面向对象编程——Object Oriented Programming,简称OOP,是一种程序设计思想。OOP把对象作为程序的基本单元,一个对象包含了数据和操作数据的函数。
我们先搞清面向对象和现象过程的区别吧。

面向过程

做一件事情,排出个步骤,第一步干什么,第二步干什么,如果出现情况A,做什么处理,如果出现情况B做什么处理。
如果问题规模小,可以步骤化,按部就班的处理。

面向对象

随着问题变得复杂,面向过程解决问题不再方便,人们将万事万物抽象为类,就是有共同特征的事物的集合。用计算机语言来描述,就是方法和属性的集合。
对象是类的具体对象,是一个实体。
面向对象的程序设计把计算机程序视为一组对象的集合,而每个对象都可以接收其他对象发过来的消息,并处理这些消息,计算机程序的执行就是一系列消息在各个对象之间传递。

一些名词

方法:类中定义的函数。
实例变量:在类的声明中,属性是用变量来表示的。这种变量就称为实例变量,是在类声明的内部但是在类的其他成员方法之外声明的。
继承:即一个派生类(derived class)继承基类(base class)的字段和方法。继承也允许把一个派生类的对象作为一个基类对象对待。例如,有这样一个设计:一个Dog类型的对象派生自Animal类,这是模拟"是一个(is-a)"关系(例图,Dog是一个Animal)。
实例化:创建一个类的实例,类的具体对象。
对象:通过类定义的数据结构实例。对象包括两个数据成员(类变量和实例变量)和方法。

面向对象三要素

1.封装
组装:将数据和操作组装到一起
隐藏数据:对外只暴露一些接口,通过接口访问对象,库模块

2.继承
多复用,继承来的就不用自己写了
多继承少修改,使用继承来改变

3.多态
面向对象编程最灵活的地方,动态绑定

python类

定义类的两种方法:
第一种方法为通过传统的方法class定义类
第二种方法为通过type类实例化定义类

python class

class ClassName:
语句块
1.必须使用class关键字
2.类名必须用大驼峰命名3.
3.类定义完成后,就产生了一个类对象,绑定到了标识符ClassName上

class MyClass:
    """allocate_lock() -> lock object"""
    x = "abc“
    def foo(self) #类属性foo,也是方法
        return "abc“
print(MyClass.x)
print(MyClass.foo)
print(MyClass.__doc__)

类对象及类属性
类对象,类的定义就会生成一个类对象
类属性,类定义中的变量和类中定义的方法都是类的属性
类变量,上例中x就是类MyClass的变量
foo是方法对象method,不是普通的函数对象function,他一般要求至少有一个参数,第一个参数可以是self(self 只是一个形参,惯用名称,可以更换),这个参数就留给对象自己,实例本身。
a= MyClass()#实例化

python__init__方法

MyClass()实际上调用的是__init__(self)方法,可以不定义,如果没有定义会在实例化后隐式调用。
作用:对实例进行初始化

class MyClass:
    def __init__(self):
        print(“test”)
print(MyClass)#不会调用
print(MyClass())#调用__init__
a = MyClass()#调用__init

python实例变量和类变量

class Person:
    age = 3
    def __init__(self,name):
        self.name = name

#tom = Person("Tom",20)
tom = Person("Tom")
jerry = Person("Jerry")

print(tom.name,tom.age)
print(jerry.name,jerry.age)
print(Person.age)
#print(Person.name)
Person.age = 30
print(Person.age,tom.age,jerry.age)

实例变量是每一个实例自己的变量,是自己独有的,类变量是类的变量,是类的所有实例共享的属性和方法。

python类特殊属性

在这里插入图片描述

装饰类的方法

例子:给Person添加类name属性

类方法

class Person:
    @classmethod
    def class_method(cls):
        print("class = {0.__name__} ({0})".format(cls))
        cls.HEIGHT = 170
Person.class_method()

使用classmethod装饰
必须至少由一个参数,用来传入class本身,cls形参只要合法即可。

静态方法

 class Person:
    @staticmethod
    def class_method(cls):
        print("class = {0.__name__} ({0})".format(cls))
        cls.HEIGHT = 170
Person.class_method()

使用static_method装饰

元类

元类是类的模板,是用来控制如何创建类的,正如类是创建对象的模板一样。

type()

class type(object):
    def __init__(cls, what, bases=None, dict=None): # known special case of type.__init__
        """
        type(object_or_name, bases, dict)
        type(object) -> the object's type
        type(name, bases, dict) -> a new type
        # (copied from class doc)
        """
        pass

通过type(name,bases,dict)就可以创建出一个类,其中
name:相当于class name中name的一个标识,是一个类名的一个标识;
bases:相当于class name (A,B)中的类继承与谁,如此时类继承于A和B这两个类 ;
dict:相当于类属性,如类的方法和属性 。

元类创建__new__

在类的多继承过程中,可以采用一个类ModelMeta从type类继承过来,然后可以通过ModelMeta类实例化创建类。

class ModelMeta(type):
    def __new__(cls, *args, **kwargs):
        print("~~~~~~~~~~~~~~~~")
        print("调用元类开始")
        print(cls)
        print(args)
        print(kwargs)
        print("~~~~~~~~~~~~~~~~~~~~~")
        return super().__new__(cls,*args,**kwargs)
C = type('test',(),{'A':10})
A = ModelMeta('test1',(),{'A':10})
print(type(C))
print(C.__dict__)
print(type(A))
print(A.__dict__)

元类创建__new__和__init__冲突

class ModelMeta(type):
    def __new__(cls, *args, **kwargs):
        print("*********")
        print("meta start")
        print(cls)
        print(args)
        print(kwargs)
        print("*********")
        return super().__new__(cls,*args,**kwargs)

    def __init__(self):
        self.name = "tom"

C = type("test",(),{"A":10})
A = ModelMeta("test1",(),{"A":10})
# print(C.__name__)
# print(C.__dict__)
print(A.__name__)
print(A.__dict__

__new__在元类编程,类实例化类的时候,用new方法实例化一个类对象,而__init__普通类实例化对象初始化属性。
ModelMeta中如果不能直接从元类中继承,只能普通根类object以下的类中继承。

在元编程过程中,类只要从元编程构造时,都会调用new方法,定义继承时要明确指定从元类中继承。
普通继承的类是元类,new方法仅会继承,但不执行
继承通过metaclass=,叫元类继承,因此叫元编程,不仅仅会继承new方法,而且会执行new方法。

魔术

魔术:容器类操作

实现容器a[“a”],a[“a”]=12,
gititem:获取容器中的某个值
setitem:给容器设置某个值
missing:当容器中的key不存在时

dicta = {"a":1,"b":2,"c":3}
class B:
    def __init__(self,dictobj):
        self.d = dictobj
    def __getitem__(self, item):
        return self.d.get(item)
    def __setitem__(self, key, value):
        self.d[key]=value
b = B(dicta)

魔术:属性查找设置

getattr:查找属性时调用此方法
instance.dict  instance.class.dict 继承的祖先类(直到object)的__dict__找不到调用__getattr__()

setattr:设置属性时调用此方法
class A:
def setattr(self,key,vaule):
self.dict[key] = value

魔术:描述器

get__类中调用别的类的对象,对外提供__get__方法,访问此类就会触发__get__方法。
set__当一个类用到了描述器,那么必然时类属性的某一值为描述器,但是实例再次设置同类一样的属性时,则触发描述器中set方法,类字典中加载此值,实例字典则不加载此值。
Python中,一个类实现了__get__、set__、delete__三个方法中的任何一个方法,就是描述器。 如果仅实现了__get__就是非数据描述符non-data descriptor 同时实现了__get__,__set__就是数据描述符data descriptor 如果一个类的类属性设置为描述器,那么它被称为owner属主。

描述器装饰器@staticmethod

class StaticMethod:
    def __init__(self,fn):
        self.fn = fn
    def __get__(self, instance, owner):
        return self.fn

class A:
    def __init__(self,name):
        self.name = name

    @StaticMethod
    def pint():
        print("Test ok")
A.pint()

描述器装饰器@classmethod

import functools
class A:
    def __init__(self,fn):
        self.fn = fn
    def __get__(self, instance, owner):
        return functools.partial(self.fn,owner)
class B:
    def __init__(self,b):
        self.b = b
    @A
    def eat(cls,g):  #eat = A(eat)= A.__init__(eat)===>eat(#此时eat函数已经将第一个参数固定未cls)
        return g
print(B.eat("g"))
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值