面向对象

定义类
# 定义类->自定义类(由程序员创建的类)
# python创建的list类
# class list(object):

# 开发 王者荣耀 ,我想创建一个悟空(对象)->类(英雄类)->类型(Hero)

# 自定义类
# class 标识这一个类

# 三种类的的创建方式都是在python2.x产生的
# object 是所有类的父类
# 02 是后期产生的
# 01 02 叫经典类,它们都是没有父类(基类)的
# 03 叫新式类

# 在python3.x中 无论写01 02 03哪种方式,都是继承object类
# 但是在python2.x中它是区分01 02 相同,而03是有父类的

# 01
class Hero:
    pass
# 02
class Hero():
    pass
# 03
class Hero(object):
    pass
创建对象
# 自定义一个悟空英雄对象
# 自定义一个英雄类
# 自定义类名 一般遵循的是大驼峰
class  Hero(object):
    # 定义一个方法(实例方法、或者对象方法)
    # 实例方法的第一个参数self
    # 实例方法 下划线或者小驼峰(公司要求)
    def move(self):
        print("英雄会走")

# 使用自定义类创建一个对象
wukong = Hero()
# 调用英雄类中的方法(想要使用其类中的方法,要使用这个类创建一个对象,使用对象调用其类里面的方法)
wukong.move()
添加和获取对象属性
# 自定义一个悟空对象
# 他会走(方法和行为,他有名字:悟空,年龄500,血量3000,攻击力400(属性和特征))

# 自定义一个英雄类
class Hero(object):
    # 方法(实例 或者 对象)
    def move(self):
        # self是谁,哪个对象调了这个方法,self就是那个对象
        print(id(self))
        print("英雄会走")

# 无论使用对象调用其类的方法或是属性,都是使用“点”语法
# 使用类创建对象
wukong = Hero()
# 执行下对象方法
wukong.move()
# 给对象添加属性
# 名字
wukong.name= "悟空"
# 年龄
wukong.age = 500
# 血量
wukong.hp = 3000
# 攻击力
wukong.atk = 400

# 获取对象身上的属性
print(wukong.name, wukong.age, wukong.hp, wukong.atk)


# 什么时候才可以给对象添加属性?
# 先要有对象才可以给这个对象添加属性

# 如何查看一个类创建的多个对象,是否是一个对象呢?
# print(wukong)
#  <__main__.Hero object at 0x00000252E13A0780>  ->16进制
# 保存到内侧中,需要开辟内存空间(底层是二进制(0,1))
# 创建 猪八戒
# zhubajie = Hero()
# print(zhubajie)
# 如果想查看10进制
print(id(wukong))
# print(id(zhubajie))

# 在类的外面使用的是对象名
# 在类的方法里面使用的是self
# 对象名 和self 本身就是一个人


# 了解  逢x进1
# 二进制 0 1
# 十进制 0 1 2 ... 9
# 16进制 0 1 2 ... ABCDEF


在方法类通过self获取获取属性
#自定义一个狗类,来创建各种名字叫旺财的狗,年龄5 皮色 黑色,会吃骨头
# 自定义一个类
class Dog(object):
    # 方法
    def eat(self):
        print("狗吃骨头")
    # 自定义一个方法,完成打印对象属性
    def info(self):
        print(self.name, self.age, self.color)

# 自定义一个旺财对象
wangcai = Dog()
wangcai.eat()
# 给对象添加属性
wangcai.name = "旺财"
wangcai.age = 5
wangcai.color = "黑色"

# 获取对象属性
# print(wangcai.name, wangcai.age, wangcai.color)
# 使用对象名调用类中的对象方法
wangcai.info()

# 在类的外面使用,使用的是对象名.属性名
# 在类的实例方法内部,使用的是self.属性名(self == 调用这个方法的对象)

__init__方法

# 自定义一个狗类
class Dog(object):

    # 构造方法
    # 在python中使用_开头,并以_结尾的称之为魔法方法
    # 魔法方法是python提供给我们的
    # object的提供的魔法方法
    # 在特殊的情况下(python可以监听到你使用自己的类创建一个对象),被python执行
    # 在自定义类(程序员自己写的类)中实现(重写)魔法方法,做自己特有的事情
    # 注意:当走进_init_方法的时候,对象已经创建成功
    def __init__(self):
        print("_init_")
        # 给对象的属性赋值
        self.name = "旺财"
        self.age = 5
        self.color = "灰色"

    # 会吃骨头
    def eat(self):
        print("会吃骨头")
    # 定义一个方法
    def info(self):
        print("名字:%s"% self.name)
        print("年龄:%s" % self.age)
        print("毛色:%s" % self.color)
        print("="*30)

# 通过自定义的类创建狗 -> 对象
# 特征,叫的名字都是旺财,年龄都是5岁,毛色都是灰色
wangcai1 = Dog()
# input("到了吗")
# 添加属性
# wangcai1.name = "旺财"
# wangcai1.age = 5
# wangcai1.color = "灰色"
# 调用对象方法
wangcai1.info()

wangcai2 = Dog()
# 添加属性
# wangcai2.name = "旺财"
# wangcai2.age = 5
# wangcai2.color = "灰色"
# # 调用对象方法
wangcai2.info()

wangcai3 = Dog()
# 添加属性
# wangcai3.name = "旺财"
# wangcai3.age = 5
# wangcai3.color = "灰色"
# 调用对象方法
wangcai3.info()

有参数的__init__方法
# 自定义一个狗类
class Dog(object):

    # 构造方法
    def __init__(self, new_name, new_age, new_color="白色"):
        # 给对象的属性赋值
        self.name = new_name
        self.age = new_age
        self.color = new_color

    # 会吃骨头
    def eat(self):
        print("会吃骨头")
    # 定义一个方法
    def info(self):
        print("名字:%s"% self.name)
        print("年龄:%s" % self.age)
        print("毛色:%s" % self.color)
        print("="*30)

# 创建旺财
wangcai = Dog("旺财", 5)
wangcai.info()
# 创建斗牛犬
douniu = Dog("斗牛犬", 4)
douniu.info()

__str__()方法
# 自定义一个英雄类
class Hero(object):

    # 构造方法
    def __init__(self, name, hp, atk):
        # 设置属性的值
        self.name = name
        self.hp = hp
        self.atk = atk

    # 打印信息
    # def info(self):
    #     print(self.name, self.hp, self.atk)

    # 实现下父类已有的魔法方法
    # 不可以添加参数(形参)
    # 会返回一个字符串
    # 追踪对象属性信息变化
    def __str__(self):
        return "名字:%s 血量:%d 攻击力:%d" % (self.name, self.hp, self.atk)

# 悟空
wukong = Hero("悟空", 4000, 400)
# wukong.info()
# 默认情况下 打印的是对象的16进制地址
# 如果类中实现了__str__方法 如果打印对象名 会输出的是__str__方法中的返回值(字符串)
print(wukong)

# __str__一般用于程序员开发调试代码

__del__()方法
# 自定义一个英雄类
class Hero(object):

    # 构造方法
    def __init__(self, name):
        # 设置属性值
        self.name = name

    # 输出一个字符串(追踪对象属性信息变化)
    def __str__(self):
        return "名字:%s" % self.name
    # 监听对象销毁会走的方法
    def __del__(self):
        print("再见")

# 创一个对象
# gailun = Hero("盖伦")
# 程序员杀死对象
# del gailun

# input("停在这里")

# python中是自动内存管理

# 创一个对象
gailun = Hero("盖伦")
gailun1 = gailun
gailun2 = gailun
# 引用计数问题
del gailun
del gailun1
del gailun2

input("停在这里")

# python中是自动内存管理

单继承
# 自定义一个师傅类
class Master(object):

    # 构造方法
    def __init__(self):
        self.kongfu = "古法煎饼果子配方"

    # 擅长做煎饼果子
    def make_cake(self):
        print("按照<%s>制造煎饼果子" % self.kongfu)

# 创建一个李师傅 对象
lishifu = Master()
print(lishifu.kongfu)
lishifu.make_cake()

# 自定义一个徒弟类
# 子类继承了父类,就拥有了父类的"方法"和"属性"
# 子类拥有了父类的属性,是因为子类使用了父类的__init__(对属性赋值的地方)
class Prentice(Master):
    pass

# 自定义一个大猫
damao = Master()
print(damao.kongfu)
damao.make_cake()

多继承
# 自定义一个师傅类-(古法)
class Master(object):

    # 构造方法
    def __init__(self):
        self.kongfu = "古法煎饼果子配方"

    # 擅长做煎饼果子
    def make_cake(self):
        print("按照<%s>制造煎饼果子" % self.kongfu)

    # 大烟袋
    def dayandai(self):
        print("大烟袋")

# 自定义一个新东方-(现代)
class School(object):

    # 构造方法
    def __init__(self):
        self.kongfu = "现代古法煎饼果子配方"

    # 擅长做煎饼果子
    def make_cake(self):
        print("按照<%s>制造煎饼果子" % self.kongfu)

    # 小烟袋
    def xiaoyandai(self):
        print("小烟袋")

# 自定义一个徒弟类
# (School, Master)哪个类在这最前面就执行该类的方法
class Prentice(Master, School):
    pass

# 自定义一个大猫
damao = Prentice()
# 为什么会打印的第一个父类的属性->古法煎饼果子配方?
# 如果两个父类的方法名(__init__)相同
print(damao.kongfu)
# 如果两个父类的方法名相同,子类会执行第一个父类
damao.make_cake()
# 如果两个父类的方法名相同。子类会分别执行
damao.dayandai()
damao.xiaoyandai()

子类重写父类的同名属性和方法
# 自定义一个师傅类-(古法)
class Master(object):

    # 构造方法
    def __init__(self):
        self.kongfu = "古法煎饼果子配方"

    # 擅长做煎饼果子
    def make_cake(self):
        print("按照<%s>制造煎饼果子" % self.kongfu)


# 自定义一个新东方-(现代)
class School(object):

    # 构造方法
    def __init__(self):
        self.kongfu = "现代古法煎饼果子配方"

    # 擅长做煎饼果子
    def make_cake(self):
        print("按照<%s>制造煎饼果子" % self.kongfu)


# 自定义一个徒弟类
# (School, Master)哪个类在这最前面就执行该类的方法
class Prentice(Master, School):
    # pass
    # 构造函数
    def __init__(self):
        self.kongfu = "猫式煎饼果子配方"

     # 擅长做煎饼果子
    # 子类继承了父类,子类重写父类已有的方法
    # 重写:子类继承父类,做自己特有的事情
    def make_cake(self):
        print("按照<%s>制作煎饼果子" % self.kongfu)

# 自定义对象  大猫
# 如果子类的方法名(子类已经重写父类的方法)和父类相同的时候,默认会使用子类的方法
# 为什么会使用子类的属性(kongfu),子类重写了父类已有的__init__方法
damao = Prentice()
damao.make_cake()

子类调用父类的同名属性和方法
# 自定义师傅类-古法
class Master(object):
    # 方法
    def make_cake(self):
        print("古法煎饼果子")

# 自定义师傅类-现代
class School(object):
    # 方法
    def make_cake(self):
        print("现代煎饼果子")

# 自定义一个徒弟类
class Prentice(Master, School):
    # 方法
    def make_cake(self):
        print("猫式煎饼果子")
    # 古法
    def old_cake(self):
        # 如果子类重写了父类已有的方法
        # 但是子类还想用父类的同名方法
        # 解决方案:父类名.对象方法名(self)
        Master.make_cake(self)
    # 现代
    def new_cake(self):
        # 同上
        School.make_cake(self)

# 自定义一个对象 大猫
damao = Prentice()
# 猫式
damao.make_cake()
# 古法
damao.old_cake()
# 现代
damao.new_cake()

super()的使用
# 自定义师傅类-古法
class Master(object):
    # 方法
    def make_cake(self):
        print("古法煎饼果子")

# 自定义师傅类-现代
class School(object):
    # 方法
    def make_cake(self):
        print("现代煎饼果子")

# 自定义一个徒弟类
class Prentice(Master, School):
    # 方法
    def make_cake(self):
        print("猫式煎饼果子")
        Master.make_cake(self)
        School.make_cake(self)
    # 古法
    def old_cake(self):

        # 01方式(单和多继承都适用)
        # Master.make_cake(self)

        # super默认会调用第一个父类的方法(适用于单继承或只想使用第一个父类的方法)

        # 02方式 ,适用于新式类
        # 格式:super(子类类名,self).父类方法名()
        # super(Prentice, self).make_cake()

        # 03方式(适用于新式类),是02方式的简写
        super().make_cake()
    # 现代
    def new_cake(self):
        # School.make_cake(self)
        super().make_cake()


# 自定义一个对象 大猫
damao = Prentice()
# 猫式
damao.make_cake()
# 古法
# damao.old_cake()
# 现代
# damao.new_cake()

私有属性和私有方法
# 自定义一个师傅类
class Master(object):

    # 构造方法
    def __init__(self):
        # 配方
        self.kongfu = "古法配方"
        # 添加一个属性
        # 如果一个属性的名字开头是两个下划线,就代表这个属性私有
        self.__money = 10000

    # 制造煎饼果子
    def make_cake(self):
        print("古法煎饼果子赚了%d元" % self.__money)
        # 在类的里面是可以使用的
        # print(self.__money)
        # self.__hellop__ython()

    # 私有的实例方法
    # 私有的作用:高大尚
    def __hellop__ython(self):
        print("我爱python")

# 自定义一个对象
lishifu = Master()
print(lishifu.kongfu)
# 如果一个属性私有后,就不能使用对象调用这个属性(类的外面使用)
# print(lishifu.__money)
lishifu.make_cake()
# lishifu.__hellop__ython()


# 自定义一个师傅类
class Master(object):

    # 构造方法
    def __init__(self):
        # 配方
        self.kongfu = "古法配方"
        # 添加一个属性
        # 如果一个属性的名字开头是两个下划线,就代表这个属性私有
        self.__money = 10000

    # 制造煎饼果子
    def make_cake(self):
        print("古法煎饼果子")

    # 私有的实例方法
    # 私有的作用:高大尚
    def __hellop__ython(self):
        print("我爱python")

# 自定义一个类 ,继承师傅类
class Prentice(Master):
    pass

damao = Prentice()
print(damao.kongfu)
damao.make_cake()
# 子类继承了父类,如果父类额属性或者方法私有后,将不会被继承


修改私有属性值
# 自定义一个人类
class Person(object):

    def __init__(self):

        self.name = "小明"
        self.age = 20

    # 定义一个方法(获取属性的值,一般方法名使用get)
    def get_age(self):
        return self.__age

    # 定义一个方法(对属性赋值的时候,一般方法名中使用set)
    def set_age(self, new_age):
        self.__age = new_age

# 间接的修改私有属性的值,和获取私有属性的值
# 对象
xiaoming = Person()
# print(xiaoming.name)

# 01 使用对象调用私有属性,完成打印age的值
print(xiaoming.get_age())
# 02 使用对象设置私有属性的值
xiaoming.set_age(30)

# 测试
print(xiaoming.get_age())


类属性和实例属性
# 自定义一个类
class Person(object):
    # 国家
    country = "中国"

    def __init__(self, name, age):
        # 实例属性(对象属性)
        self.name = name
        self.age = age


# xiaoming = Person("小明", 20)
#
# 使用实例属性: 对象名.实例属性名
# print(xiaoming.name)

# 修改实例属性: 对象名.实例属性名 = 值
# xiaoming.name = "小明明"
# print(xiaoming.name)

# 使用类属性
# 01: 类名.类属性名
# print(Person.country)
# 02: 对象名.类属性名
# xiaoming = Person("小明", 20)
# print(xiaoming.country)


# 修改类属性
# 01: 类名.类属性名 = 值
# Person.country = "中华"
# print(Person.country)

# 02: 不存在(对象名.类属性名 = 值)
# xiaoming = Person("小明", 20)
# # python认为你是给对象设置实例属性(只是和类属性名相同而已)
# xiaoming.country = "中华"
# print(xiaoming.country)
# print(Person.country)


# 关于类属性 内存问题
# xiaoming1 = Person("小明1", 20)
# xiaoming2 = Person("小明2", 20)
# 类属性python只会开辟一份内存(他是代表这个类的属性这个类python中只有一个)
# print(id(xiaoming1.country))
# print(id(xiaoming2.country))
# print(id(Person.country))


# 类属性好处???
# 为了节约内存
# 为了后期业务需求更改 可以提高开发效率
# 自定义一个类
class Person(object):
    # 国家
    # country = "中国"
    def __init__(self, name, age, country):
        # 实例属性(对象属性)
        self.name = name
        self.age = age
        self.country = country

类方法
# 自定义一个类
class Person(object):

    # 类属性(私有)
    __country = "中国"


    # 定义类方法
    # 获取私有类属性的值
    # cls = 类名
    # 修饰器
    @classmethod
    def get_country(cls):
        return cls.__country

    # 修改私有类属性的值
    @classmethod
    def set_county(cls, new_county):
        cls.__country = new_county

# 01:类名.类方法(调用类方法)
# print(Person.get_country())

# Person.set_county("中华")
# print(Person.get_country())

# 02:对象名.类方法(调用方法)
xiaoming = Person()
# 调用类方法
print(xiaoming.get_country())
xiaoming.set_county("中华")
print(xiaoming.get_country())

静态方法
# 值自定义类
class Person(object):

    # 私有类的属性(国籍)
    __country = "中国"

    # 构造方法
    def __init__(self):

        self.name = "小明"
        # 私有
        self.__age = 20

    # 实例方法(对象方法)获取私有属性
    def get_age(self):
        return self.__age

    # 实例方法(对象方法)修改私有属性
    def set_age(self, new_age):
        self.__age = new_age

    #类方法
    @classmethod
    def get_country(cls):
        return cls.__country

    # 类方法
    # 修改类方法
    @classmethod
    def set_country(cls, new_country):
        cls.get_country = new_country

    # 静态方法
    @staticmethod
    def hello():
        print("今天天气不错")

# 使用静态方法
# 01:类名.静态方法名
# Person.hello()

'''
python中类中的方法总结:

- 实例方法(对象方法) -> 场景最多
    - 定义格式:def 实例方法名(self):
    - 调用格式:对象名.实例方法名()
    - 使用场景:在方法中需要self
    
- 类方法 -> 对私有属性取值或者赋值
    - 定义格式:@classmethod
                def 类方法名(cls):
    - 调用格式:类名.类方法名() 或者 对象名.类方法名()
    - 使用场景:在方法中需要cls(类名)
    
- 静态方法 -> 一般不用
    -定义格式:@staticmethod
                def 静态方法名():
    - 调用格式:类名.类方法名() 或者 对象名.类方法名()
    - 使用场景:在方法中不需要self,也不需要cls  
'''

__new__()方法
# 自定义一个人类
class Person(object):

    # 监听python使用其类创建对象,并返回对象 -> __init__
    def __new__(cls, *args, **kwargs):
        print("__new__")
        # return object.__new__(cls)

    # 构造方法(监听python使用其类创建对象完成,给这个对象设置属性)
    def __init__(self):
        print("__init__")
        self.name = "小明"

    # 监听对象属性信息变化
    def __str__(self):
        return "名字:%s" % self.name

    # 监听对象销毁
    def __del__(self):
        print("再见")

# 创建一个对象
xiaoming = Person()
print(xiaoming)

# None 空值类型
# <class 'NoneType'>
print(type(None))

单例模式
# 单例模式 在程序中这个类创建出来的对象 只有一个(也就是占用一份内存地址)
# 单例模式 也只会走一次__init__方法(保证这个单例对象的属性也是唯一的)(name=小明 age=20)
# 合理的使用内存(避免内存浪费)
class Person(object):

    # 定义一个类属性  保存这个类创建的对象
    __instance = None
    # 定义一个类属性 判断是否是第一次走init方法
    __is_first = True
    # 创建对象
    # 重写new方法 是为了完成单例模式中的对象地址唯一
    def __new__(cls, *args, **kwargs):
        # 判断是否通过这个类创建过对象
        # 如果没有值需要创建
        if not cls.__instance:
            # 创建对象保存起来
            cls.__instance = object.__new__(cls)

        # 如果有值直接返回
        return cls.__instance

    def __init__(self, name, age):
        # 判断是否是第一次
        if Person.__is_first:
            # 赋值一次
            self.name = name
            self.age = age
            # 设置类属性is_first 为False
            Person.__is_first = False

    # def make(self):
    #
    #     hm = HMTest()
    #     hm.my_func(20, 30)


# 创建对象
xiaoming = Person("小明", 20)
print(xiaoming.name)
xiaohong = Person("小红", 21)
print(xiaohong.name)
xiaoyang = Person("小阳", 22)
print(xiaoyang.name)
#
print(xiaoming.name, xiaohong.name, xiaoyang.name)


# num = None
# # 如果不为none 也就是真
# if not num:
#     print("测试")


# 单例的好处?
class HMTest(object):
    def my_func(self, a, b):
        return a + b


# 在程序中 需要计算多次求和操作 比如1000次 可以省掉999分内存
# 每次使用
# 实例化一个对象
# hm = HMTest()
# hm.my_func(10, 20)

# 为了节约内存


 
原文地址:https://www.cnblogs.com/yaoteng/p/10918893.html