zoukankan      html  css  js  c++  java
  • python3 初识面向对象

    """
    语法:
    class 类名
    图纸就是一个类,根据图纸造出来的每辆车就是一个对象。
    
    1、属性:能够描述一个对象的变量(变量)
    2、动作:能够描述一个对象能执行的动作(函数)

    在类中访问属性:self.属性
    在类中访问动作:self.动作
    """ class Car: def __init__(self, color): # self就是对象 self.color = color # 属性 def run(self): # 动作 print("我的车会跑") # 创建对象 init 初始化 出厂设置 c1 = Car("red") # 类名() => 实际上默认执行的是__init__函数 c2 = Car("white")

    self到底是个什么鬼?

    class Car:
        def __init__(self, color):  # self就是对象
            print(self)  # self到底是个什么鬼
            self.color = color  # 属性
    
        def run(self):  # 动作
            print("我的车会跑")
    
    
    c1 = Car("red")  
    print(c1)

    执行结果:

    <__main__.Car object at 0x000000000228CEB8>
    <__main__.Car object at 0x000000000228CEB8>

     结论:self就是对象

    不同对象调用同一方法,会有什么样的效果呐?

    class Car:
        def __init__(self, color):  # self就是对象
            print(self)  # self到底是个什么鬼
            self.color = color  # 属性
    
        def run(self):  # 动作
            print(f"我的{self.color}车会跑")
    
    
    c1 = Car("red")  
    c2 = Car("white")
    c1.run()
    c2.run()

    执行结果:

    <__main__.Car object at 0x00000000029997F0>
    <__main__.Car object at 0x0000000002999828>
    我的red车会跑
    我的white车会跑

    结论:不同对象调用同一属性或方法,调用的是对象自己的属性和方法。

    接下来,看下类的成员-->变量

    """
    类的成员
        1、变量
            1.实例变量 实例=对象 对象的属性值 必须用:对象.变量
            2.类变量 直接写在类中的变量 推荐用:类名.变量
    """
    class Person:
        country = "中国"  # 类变量
    
        def __init__(self, name, age):
            self.name = name  # 实例变量
            self.age = age
    
    
    p = Person("lily", 18)
    print(p.name)  # 对象.实例属性
    print(p.age)
    print(p.country)  # 不推荐使用,对象中没有,则去类中找
    print(Person.country)  # 推荐使用
    # print(Person.name)  # 报错AttributeError: type object 'Person' has no attribute 'name'

    执行结果:

    lily
    18
    中国
    中国

     对象.属性可以新建一个属性

    class Person:
        country = "中国"  # 类变量
    
        def __init__(self, name, age):
            self.name = name  # 实例变量
            self.age = age
    
    
    p = Person("lily", 18)
    p.country = "大清"  # 对象中没有,则新建一个country
    print(p.country)
    print(Person.country)  # 类变量

    执行结果:

    大清
    中国

     

    对象访问类变量的情况(理解很重要!!!)

    class Person:
        country = "中国"  # 类变量
    
        def __init__(self, name, age):
            self.name = name  # 实例变量
            self.age = age
    
    
    p = Person("lily", 18)
    print(p.country)
    print(Person.country)  # 类变量
    Person.country = "大清"
    print(p.country)

    执行结果:

    中国
    中国
    大清

     类的成员-->方法

    """
    类的成员
        2、方法:在类中写的函数
            1.实例方法 必须对象.方法 第一个参数必须是self
            2.类方法 推荐使用类名.方法 添加@classmethod装饰器 第一个参数必须是cls 一般用来创建对象
            3.静态方法 推荐类名.方法 添加@staticmethond装饰器 参数无要求 一般用来写逻辑运算
    
            总结:
                实例方法必须先创建对象,再通过对象访问实例方法
                类方法和静态方法是在创建对象前执行的方法(不需要对象就能执行的方法:类方法和静态方法)。
    """
    class Person:
    
        def __init__(self, name):
            self.name = name
    
        def run(self):  # 需要访问实例属性和方法的情况
            print(f"我是run实例方法,我的名字是{self.name}")
    
        @classmethod
        def play(cls):  # cls就是类  类方法一般用来创建对象
            print("我是play类方法")
    
        @staticmethod
        def study():  # 静态方法一般用来写逻辑运算
            print("我是study静态方法")
    
    
    p = Person("lily")
    p.run()  # 实例方法,必须使用对象来访问
    # Person.run()  # TypeError: run() missing 1 required positional argument: 'self'
    Person.play()  # 推荐使用 类方法推荐使用类名来访问
    p.play()  # 不推荐使用
    Person.study()  # 推荐使用  静态方法推荐使用类名来访问
    p.study()  # 不推荐使用

    执行结果:

    我是run实例方法,我的名字是lily
    我是play类方法
    我是play类方法
    我是study静态方法
    我是study静态方法

    cls是个什么鬼?

    class Person:
        def __init__(self, name):
            self.name = name
    
        @classmethod
        def play(cls):  # cls 就是类
            print(cls)
            print("我是play类方法")
    
    p = Person("lily")
    print(Person)
    Person.play()

    执行结果:

    <class '__main__.Person'>
    <class '__main__.Person'>
    我是play类方法

    结论:cls就是类

    类方法的使用实例(用户登录)

    class User:
        menu = ["查看所有课程", "选择课程", "查看已选课程", "删除已选课程"]
    
        def __init__(self, username):
            self.username = username
    
        def display_menu(self):
            print("显示可菜单内容")
    
        @classmethod
        def login(cls):  # 类方法,一般会用来创建对象
            for i in range(2, -1, -1):
                username = input("Username: ").strip()
                password = input("Password: ").strip()
                if username == "lily" and password == "123":
                    print("登录成功!")
                    return cls(username)  # 返回一个对象
                else:
                    print("登录失败!")
                    return None
    
    
    if __name__ == '__main__':
        user_obj = User.login()
        if user_obj:
            user_obj.display_menu()

    类的成员-->属性

    """
    类的属性
        在方法的上面加上一个@property的装饰器,可以把一个方法变成属性
    """
    class Person:
        def __init__(self, name ,birth_year):
            self.name = name
            self.birth_year = birth_year
    
        @property  # property装饰器可以把一个方法变成属性 从age中拿到数据
        def age(self):
            print(f'今年是{time.strftime("%Y")}年')
            return int(time.strftime("%Y")) - self.birth_year
    
    
    import time
    p = Person("lily", 2001)
    print(p.age)

    执行结果:

    今年是2019年
    18

    给age赋值

    class Person:
        def __init__(self, name, birth_year):
            self.name = name
            self.birth_year = birth_year
    
        @property  # property装饰器可以把一个方法变成属性
        def age(self):
            print(f'今年是{time.strftime("%Y")}年')
            return int(time.strftime("%Y")) - self.birth_year
    
        @age.setter  # 给age赋值
        def age(self, value):
            self.birth_year = int(time.strftime("%Y")) - value
    
    
    if __name__ == '__main__':
        import time
    
        p = Person("lily", 2001)
        print(p.age)
        p.age = 10
        print(p.age)

    执行结果:

    今年是2019年
    18
    今年是2019年
    10

    类的私有成员(双线划线开头的变量或方法都是私有的,只能在类中使用。)

    """
    类的成员
        私有:只能在类中使用,__双下划线开头的变量或方法都是私有的。
            另外,_单线划线开头的变量或方法都是给子类使用的。
    """
    class Person:
        __hobby = "高尔夫"  # 私有类变量
    
        def __init__(self, username, wife_name):
            self.username = username
            self.__wife_name = wife_name  # 私有变量
    
        def tell(self):
            print(f"{self.username}妻子的名字叫{self.__wife_name}")
    
        def __play(self):  # 私有方法
            print(f"{self.username}偷偷的去耍牌去了")
    
    
    p = Person("吴奇隆", "刘诗诗")
    # print(p.__wife_name)  # AttributeError: 'Person' object has no attribute '__wife_name'
    p.tell()
    # print(p.__play())  # AttributeError: 'Person' object has no attribute '__play'
    # print(Person.__hobby)  # AttributeError: type object 'Person' has no attribute '__hobby'

    执行结果:

    吴奇隆妻子的名字叫刘诗诗

    类的特殊成员

    """
    类的特殊成员
        __new__ 开辟内存
        __init__ 类名()的时候调用
        __call__ 对象()的时候调用
        __getitem__ 取数据
        __setitem__ 设置数据
        __delitem__ 删除数据
    """
    class Foo:
        def __init__(self):  # 初始化
            self.dic = {}
            print("类名()的时候调用")
    
        def __call__(self):
            print("对象()的时候调用")
    
        def __getitem__(self, item):
            print("取数据")
            return self.dic.get(item)
    
        def __setitem__(self, key, value):
            print("设置数据", key, value)
            self.dic[key] = value
    
        def __delitem__(self, key):
            print("删除数据")
            self.dic.pop(key)
    
    
    f = Foo()  # __init__
    f()  # __call__
    f["name"]  # __getitem__
    f["age"] = 18  # __setitem__
    print(f["age"])
    del f["age"]  # __delitem__

    执行结果:

    类名()的时候调用
    对象()的时候调用
    取数据
    设置数据 age 18
    取数据
    18
    删除数据

    __new__是个什么鬼?什么时候执行?__new__和__init__的先后顺序?

    class Foo:
    
        def __new__(cls, *args, **kwargs):
            print("我是__new__")
    
        def __init__(self):
            print("我是__init__")
    
    
    f = Foo()

    执行结果:

    我是__new__

    发现没有,__init__没有执行,只是执行了__new__方法。在每个类中默认都有一个__new__方法,用来开辟内存,这里写了,就覆盖了默认的__new__方法。那到底怎么开辟内存呐?

    class Foo:
    
        def __new__(cls, *args, **kwargs):  # 在每个类中默认有__new__方法,这里写了,就覆盖了默认的__new__方法
            print("我是__new__")
            return object.__new__(cls)  # 开辟内存
    
        def __init__(self):
            print("我是__init__")

    执行结果:

    我是__new__
    我是__init__

     

    类的继承 (子类可以访问父类非私有的变量、方法和属性,父类不能访问子类独有的变量、方法和属性。

    """
    类的继承
        子类可以访问父类的变量、方法和属性,父类不能访问子类独有的变量、方法和属性。
    """
    class Animal:
        def action(self):
            print("动物会动")
    
    
    class Cat(Animal):  # Cat继承Animal
        def catch_mouse(self):
            print("猫会抓老鼠")
    
    
    a = Animal()
    c = Cat()
    a.action()
    c.action()  # Cat类中没有action方法,也就是自己类中没有,就去父类中找
    # a.catch_mouse()  # 报错AttributeError: 'Animal' object has no attribute 'catch_mouse'
    c.catch_mouse()

    执行结果:

    动物会动
    动物会动
    猫会抓老鼠

    子类和父类有相同的方法时,子类会重写父类的方法,子类实例会调用自己类中的方法。

    class Animal:
        def action(self):
            print("动物会动")
    
    
    class Cat(Animal):  # Cat继承Animal
        def action(self):  # 重写父类的方法
            print("猫会动")
    
        def catch_mouse(self):
            print("猫会抓老鼠")
    
    
    c = Cat()
    c.action()

    执行结果:

    猫会动

    类的多继承

    """
    类的多继承:
        一个类可以继承多个类
            先在对象自己类中找,找到了,就自己类中的方法,没找到,再去父类中找 ,根据mro的顺序查找。
    """
    class Father:
        def play(self):
            print("Father陪你玩!")
    
    
    class Mother:
        def play(self):
            print("Mother陪你玩!")
    
    
    class Child(Father, Mother):  # Child继承Father和Mother
        pass
    
    
    s = Child()
    s.play()  # 自己类中没有,按照继承的顺序(mro)去父类中找
    print(Child.mro())  # mro: Method Resolution Order

    执行结果:

    Father陪你玩!
    [<class '__main__.Child'>, <class '__main__.Father'>, <class '__main__.Mother'>, <class 'object'>]

    super()在类的继承中的使用

    class Father:
        def play(self):
            print("Father陪你玩!")
    
    
    class Mother:
        def play(self):
            print("Mother陪你玩!")
    
    
    class Child(Father, Mother):  # Child继承Father和Mother
        def play(self):
            print("Child自己玩!")
            super(Child, self).play()  # 使用self对象去执行mro里Child类的下一个类的play方法
            super().play()  # 执行mro里当前类的下一个类的play方法,结果同上(推荐使用这种方法)
            super(Father, self).play()  # 使用self对象去执行mro里Father类的下一个类的play方法
    
    
    s = Child()
    s.play()  # 自己类中没有,按照继承的顺序(mro)去父类中找
    print(Child.mro())  # mro: Method Resolution Order

    执行结果:

    Child自己玩!
    Father陪你玩!
    Father陪你玩!
    Mother陪你玩!
    [<class '__main__.Child'>, <class '__main__.Father'>, <class '__main__.Mother'>, <class 'object'>]

    初始化父类的__init__方法

    class Father:
        def __init__(self, address):
            self.address = address
    
    
    class Child(Father):
        def __init__(self, name, age, address):
            super().__init__(address)  # 继承父类的__init__方法
            self.name = name
            self.age = age
    
    
    c = Child("lily", 18, "洛杉矶")
    print(c.address)

    执行结果:

    洛杉矶

     

     python2和python3在继承这块的区别

    """
    类的多继承:
        一个类可以继承多个类
            先在对象自己类中找,找到了,就自己类中的方法,没找到,再去父类中找 ,根据mro的顺序查找。
            python3 新式类  广度优先
            python2 经典类 深度优先
    """
    class Grandfather:
        def play(self):
            print("Grandfather陪我玩!")
    
    
    class Father(Grandfather):
        pass
    
    
    class Mother(Grandfather):
        def play(self):
            print("Mother陪我玩!")
    
    
    class Child(Father, Mother):
        pass
    
    
    c = Child()
    c.play()
    print(Child.mro())

    执行结果:

    Mother陪我玩!
    [<class '__main__.Child'>, <class '__main__.Father'>, <class '__main__.Mother'>, <class '__main__.Grandfather'>, <class 'object'>]

    需要记住:

      python3 新式类 广度优先

      python2 经典类 深度优先

    类的成员

    1、变量

       1.实例变量 实例=对象 对象的属性值 必须用:对象.变量

       2.类变量 直接写在类中的变量 推荐用:类名.变量

    2、方法(在类中写的函数 )

      1.实例方法 必须对象.方法 第一个参数必须是self

      2.类方法 推荐使用类名.方法 添加@classmethod装饰器 第一个参数必须是cls 一般用来创建对象

      3.静态方法 推荐类名.方法 添加@staticmethond装饰器 参数无要求 一般用来写逻辑运算

    3、类的属性

      在方法的上面加上一个@property的装饰器,可以把一个方法变成属性

    4、类的成员

      私有:只能在类中使用,__双下划线开头的变量或方法都是私有的。

      另外,_单线划线开头的变量或方法都是给子类使用的。

    5、特殊方法

       __init__ 初始化

      __call__ 对象()的时候调用

      __getitem__ 取数据

      __setitem__ 设置数据

      __delitem__ 删除数据

    
    
    
    
  • 相关阅读:
    函数
    数组
    类的例题
    异常语句
    类的学习
    for的穷举、迭代
    for循环
    switch case
    反相器,扇入扇出
    T触发器,JK触发器的verilog实现
  • 原文地址:https://www.cnblogs.com/lilyxiaoyy/p/11988523.html
Copyright © 2011-2022 走看看