python的面向对象

面向对象的概念

  面向过程和面向对象是两种编程方式,这两个种方式是程序员用来代码来抽象世界的不同的方式,本身无优劣之分,针对于不同的抽象,各有利弊。面向对象更倾向于用各种模板来抽象世界,每个实例就是这种抽象的具体描述,这样可以描述更加复杂的关系,且可以让行为和属性和具体的对象进行绑定。而面向过程更倾向于描述解决问题的一种流程,更加的直观,简洁高效。

一个简单的栗子:

class Dog(object):
    def __init__(self, name, bleed, age):
        self.name = name
        self.bleed = bleed
        self.age = age

    def speak(self):
        print("wang!wang!wang!")

    def show(self):
        print('我叫 %s 我是一只 %s 狗,我今年 %s 岁了' % (self.name, self.bleed, self.age))

d = Dog("mjj", "京巴", 3)
d.speak()
d.show()

具体定义描述
class Dog(object):

首先class 是一个关键字,标志了需要定义一个类;

Dog 是这个定义的类的名字,后面我们通过这个类的名字进行数据的实例化调用

(object)是表示此类继承了object类,括号中是父类的名字,python支持多继承,所以在括号内可以写多个类名,但是需要用逗号进行分割!

  *object是所有python定义类的父类,默认继承,若没有具体的类要继承 那么无需写object,因为可以省略。

类中的方法:

    def speak(self):
        print("wang!wang!wang!")

方法定义没有任何特殊,但是和一般的方法定义,有一个默认的参数,self,这个self标志是实例自己。方法中可以使用self来调用自己的一些实例属性值,类属性的值,可以使用类名.类属性名来进行访问

d = Dog("mjj", "京巴", 3)
创建一个名字叫d实例,它是Dog的一个具体的对象。初始化默认就会调用类的__init__(self,xxxx)方法,因为这个方法是实例方法,所以,self默认,只需要进行self后的形参列表进行传值即可。
d.speak()
使用实例名称.方法名称调用方法,执行你所需的逻辑。

概念解析

类:class关键字后面定义的代码,可以看作一个类的定义。有时候我们说的类,其实就是这样的类的定义。
类名:可以看作一个模板,在创建实例的时候进行调用
实例名: 通过调用类名()创建的一个类的实例的名字,叫做实例名
类方法:一般会有一个@classmethod标签 通过 类名.方法名 / 实例名称.方法名 进行调用,可以访类变量,但是不能访问实例变量
实例方法:只能通过 实例变量.方法 名称
进行调用,可以访类变量,可以访问实例变量
静态方法:一般会有一个@staticmethod标签

对象之间的关系

组合关系:某些东西只有在一起的时候才能正常工作,下面这个weapon和person就是一个组合关系

class Dog():
__force_dict = {'京巴': 30, '藏獒': 80}

def __init__(self, name, bleed, age):
self.name = name
self.bleed = bleed
self.age = age
self.life_val = 100
self.force_val = Dog.__force_dict.get(bleed)

@classmethod
def speek(self):
print("wang!wang!wang!")

def bite(self, p):
p.life_val -= self.force_val
print("%s 张口咬了 %s , %s 掉血 %s 还剩 %s 血量" % (self.name, p.name, p.name, self.force_val, p.life_val))


class Weapon():

def knift(self, d):
d.life_val -= 80
print("拿刀捅了 %s , %s 掉血 %s 还剩 %s 血量" % (d.name, d.name, 80, d.life_val))

def gun(self, d):
d.life_val -= 100
print("拿枪扫射了 %s , %s 掉血 %s 还剩 %s 血量" % (d.name, d.name, 100, d.life_val))

def stick(self, d):
d.life_val -= 50
print("拿打狗棍打了 %s , %s 掉血 %s 还剩 %s 血量" % (d.name, d.name, 50, d.life_val))


class Person():
def __init__(self, name, sex, age):
self.name = name
self.sex = sex
self.age = age
self.life_val = 100
self.weapon = Weapon()


d = Dog('mjj', '京巴', 3)

p = Person('ty', 'male', 30)

d.bite(p)

p.weapon.knift(d)

两个对象之间存在组合的关系,一方是另外一方的某个实例属性,这样的关系,叫做组合关系。

依赖关系

class Dog():
    def __init__(self, name, bleed, age, person):
        self.name = name
        self.bleed = bleed
        self.age = age
        self.person = person

    def say_hi(self):
        print("我是%s,我的主人是%s" % (self.name, self.person.name))


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


p = Person('tang', 'male', 30)

d = Dog('mjj', '京巴', 3, p)
d.say_hi()

 

关联关系

class Relationship():
    def __init__(self):
        self.couple = []

    def make_couple(self, obj, obj2):
        self.couple = [obj, obj2]

    def break_up(self):
        self.couple = []

    def get_parter(self, obj):
        if len(self.couple) > 0:
            for temp in self.couple:
                if obj != temp:
                    return temp

        
        return None


class Person():
    def __init__(self, name, sex, age, relation):
        self.name = name
        self.sex = sex
        self.age = age
        self.life_val = 100
        self.relation = relation


relationship = Relationship()
p1 = Person('mjj', 'male', 24, relationship)
p2 = Person('zqq', 'famale', 23, relationship)
relationship.make_couple(p1, p2)

print(p1.relation.get_parter(p1).name)
print(p2.relation.get_parter(p2).name)

 

聚合关系:

 

继承关系

狗继承自动物,所以有动物的所有特性,动物的方法也可以被狗使用

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

    def eat(self):
        print("动物吃东西狼吞虎咽!")


class Dog(Animal):
    def __init__(self, name, age, bleef):
        super().__init__(name, age)
        self.bleef = bleef

    def show(self):
        print("狗在表演站立")


d = Dog('mjj', 3, '京巴')
d.eat()
d.show() 

 

类的三大特性

继承:参看上面

封装:将一些不希望被在类外调用的方法或者属性进行隐藏,这样的方式叫做封装

封装方法:在方法名字前加 __(两个下划线)

封装属性:在属性前面加__(两个下划线)

这样在调用的时候会出现如下错误:AttributeError: 'Dog' object has no attribute 'xxx'

强制调用封装函数:对象._类名+方法名()

d._Dog__show()

多态性

子类重写了父类的方法,那么通过子类调用此方法,那就会先找子类的方法列表中是否存在,不存在,会按照继承顺序,依次向上查找父类,找到就调用。

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

    def eat(self):
        print("动物吃东西狼吞虎咽!")


class Dog(Animal):
    def __init__(self, name, age, bleef):
        super().__init__(name, age)
        self.bleef = bleef

    def __show(self):
        print("狗在表演站立")
    
    def eat(self):
        print("狗吃东西吧唧嘴!")


d = Dog('mjj', 3, '京巴')
d.eat()

d._Dog__show()

这个eat方法就是体现了多态性!

 

方法的标签

@property

 

class Flight:
    def __init__(self, airline):
        self.airline = airline
        self.__flight_sta = None

    @property
    def flight_status(self):
        print("通过机场的航班查询飞机的状态。。。")
        if self.__flight_sta == 0:
            print("飞机还未到达机场")
        elif self.__flight_sta == 1:
            print("飞机正在登机")
        elif self.__flight_sta == 2:
            print("飞机已经离开机场")

    @flight_status.setter
    def flight_status(self, value):
        self.__flight_sta = value


f = Flight("M219")
# f.flight_status
f.flight_status = 1
f.flight_status

可以将方法看作一个属性来范文,设置属性也可以当作一个属性来赋值

热加载 

__import__("XXXX")
或者(官方推荐使用类库的方式进行加载)

import importlib
importlib.import_module("XXXX")

 

双下划线方法

# 两个对象是否相等 isinstance()方法可能会用到
def __eq__(self, other):
    pass

# 获取实例属性的长度会调用此方法 def __len__(self): pass #计算hash的结果值会调用此方法 def __hash__(self): pass #获取某个属性会调用此方法 def __getitem__(self, item): pass #设置属性值会调用此方法 def __setitem__(self, key, value): pass #删除属性值会调用此方法 def __delitem__(self, key): pass

def __init__(self):
pass

#类似STR函数 但是场景有不一样
def __repr__(self):
pass
#直接使用print(obj)则调用此函数
def __str__(self):
pass
#删除对象时候调用
def __del__(self):
pass

析构函数

 创建和销毁对象会用到的函数 称之为析构函数

def __init__(self):
    pass
def __repr__(self):
    pass

 

反射

 反射主要是通过这

hasattr(),getattr(),setattr(),delattr()来进行设置
if hasattr(d, 'name'):
    obj = getattr(d, 'name')
    print(obj)

if hasattr(d, 'show'):
    obj = getattr(d, 'show')
    if callable(obj):
        print('是函数')
        obj()


def print_char(char, num):
    val = char * num
    print(val)
setattr(d, "print_char", print_char)
d.print_char("*", 10)

 

单例模式和__new__()

class Printer():
    instance = None

    def __init__(self, file):
        if hasattr(self, "files"):
            self.files.append(file)
        else:
            self.files = []
            self.files.append(file)

    def print(self):
        for temp in self.files:
            print(temp)

    def __new__(cls, *args, **kwargs):
        if cls.instance == None:
            cls.instance = super().__new__(cls)

        return cls.instance


p1 = Printer("pdf")
p2 = Printer("word")
p3 = Printer("excel")

print(p1, p2, p3)

p3.print()

 

posted @ 2024-02-27 18:03  琼尼-沃克  阅读(3)  评论(0编辑  收藏  举报