编程语言
首页 > 编程语言> > Python学习整理记录之OPP面向对象(类)

Python学习整理记录之OPP面向对象(类)

作者:互联网

OOP-Python面向对象

1 面向对象概述(Object Oriented,OO)

2 类的基本实现

class Student():
    name = "dana"
    age = 19    
    def say(self):
        self.name = "aa"
        self.age = 20
        print("my name is {0}".format(self.name))
        print("my age is {0}".format(self.age))

#类实例的属性和其对象的实例的属性,在不对对象的实例属性进行赋值的情况下,指向同一个变量        
#Student是一个类实例
print(Student.name)
print(Student.age)        
    def sayAgain(s):
        s.name = "bb"
        s.age = 21
        print("my name is {0}".format(s.name))
        print("my age is {0}".format(s.age))                
    def saySomething():
        print("my name is {0}".format(__class__.name))
        print("my age is {0}".format(__class__.age))                
        print("Say Something Again!")    
t = Student()
t.say()
t.sayAgain()
# 调用绑定类函数必须使用类名
Student.saySomething()

my name is aa
my age is 20
my name is bb
my age is 21
Say Something Again!

3 anaconda基本使用

4 类和对象的成员分析

5 关于self

class A():
    name = "liuying"
    age = 18
# 私有    
    def __init__(self):
        self.name = "bde"
        self.age = 390
    def say(self):
        print(self.name)
        print(self.age)
class B():
    name = "ccccc"
    age = 89    
a = A()
# 系统会默认把a作为第一个参数传入函数
a.say()
# 此时,self被a替换
A.say(a)
# 同样可以把A作为参数传入
A.say(A)
#此时,把B作为参数传入,条件是B具有与A相同的属性,所以不会报错
A.say(B)
A.__dict__

bde
390
bde
390
liuying
18
ccccc
89
mappingproxy({'module': 'main',
'name': 'liuying',
'age': 18,
'init': <function main.A.init(self)>,
'say': <function main.A.say(self)>,
'dict': <attribute 'dict' of 'A' objects>,
'weakref': <attribute 'weakref' of 'A' objects>,
'doc': None})

6 面向对象的三大特性

6.1 封装

# 私有变量案例
class Person():
# name是共有成员
    name = "liuyun"
 # __age是私有成员
    __age = 18    
P = Person()
print(P.name)
# 注意报错信息 AttributeError: 'Person' object has no attribute '__age'
print(P.__age)

AttributeError Traceback (most recent call last)
in
8 P = Person()
9 print(P.name)
---> 10 print(P.__age)

AttributeError: 'Person' object has no attribute '__age

6.2 继承

继承的语法

# 继承的语法
# 在python中,任何类都有一个共同的父类叫做object
class Person():
    name = "NoName"
    age = 19
    __score = 99     # 分数是秘密,私有不可访问
    _petname = "ABC" # 小名受保护,子类可以访问,
    def sleep(self):
        print("Sleeping.....")
# 父类 写在括号内
class Teacher(Person):
    teacher_id = '8956'
    name = 'dadna'
    def make_test(self):
        print("attention")
t = Teacher()
# 子类和父类定义同一个名称变量,则优先使用子类本身
print(t.name)
# 子类访问父类受保护成员
print(t._petname)
# 子类不允许访问父类的私有成员
print(t.__score)

dadna
ABC

AttributeError Traceback (most recent call last)
in
26
27 # 子类不允许访问父类的私有成员
---> 28 print(t.__score)
29
30

AttributeError: 'Teacher' object has no attribute '__score

继承的特征

# 子类扩充父类功能的案例
# 父类有工作的函数,子类也有工作的函数,
class Person():
    name = "NoName"
    age = 19
    __score = 99     # 分数是秘密,私有不可访问
    _petname = "ABC" # 小名受保护,子类可以访问,
    def sleep(self):
        print("Sleeping.....")
    def work(self):
        print("Make some money !")
# 父类 写在括号内
class Teacher(Person):
    teacher_id = '8956'
    name = 'dadna'
    def make_test(self):
        print("attention")   
    def work(self):
        # 扩充父类的功能只需要调用父类相应的函数
        # Person.work(self)
        # 另一种方法
        super().work()
        self.make_test()
t = Teacher()
t.work()
# 构造函数的概念
class Person():
    # __init__就是构造函数
    # 每次实例化的时候,第一个被调用
    # 因为主要工作是进行初始化,所以得名
    def __init__(self): # self参数必须有,可以是其他命名        
        # 以下是初始化数据。
        self.name = "Wava"
        self.age = 19
        self.address = "Guangdong,China"
        print("{0} is initing and {1}years old,live in {2}".format(self.name,self.age,self.address))
p = Person()
Person()
# 构造函数的调用顺序 1
# 如果子类没有写构造函数,则自动向上查找父类,只到找到构造函数
class A():
    pass
class B(A):
    pass
class C(B):
    # __init__就是构造函数
    # 每次实例化的时候,第一个被调用
    # 因为主要工作是进行初始化,所以得名
    def __init__(self):  # self参数必须有,可以是其他命名
        print("I am initing.....in C")
# 实例化的时候,首先查找C的构造函数,找到就停止查找
c = C()


# 构造函数调用顺序 2
class A():
    def __init___(self):
        print("I am initing...in A")
class B(A):
    def __init__(self):
        print("I am initing....in B")
class C(B):
    pass
# 在C类找不到构造函数,则向上按照MRO顺序查找B父类的构造函数
c = C()


# 构造函数调用顺序 3
class A():
    def __init___(self):
        print("I am initing...in A")
class B(A):
    def __init__(self,name):
        print("I am initing....in B")
        print(name)
class C(B):
    pass
# 此时如果C()没有参数,则会出现参数结构不对应的错误
# <TypeError: __init__() missing 1 required positional argument: 'name'>
#c = C()
# 当C()存在参数时,则运行正常
c = C("NONO")


# 继承中的构造函数 4
class Animal():
    pass
class Reptile(Animal):
    def __init__(self, name):
        self.name = name
        print("{0} are Reptile".format(self.name))
class dog(Reptile):
    # __init__就是构造函数
    # 每次实例化的时候,第一个被调用
    # 因为主要工作是进行初始化,所以得名
    def __init__(self):  # self参数必须有,可以是其他命名
        print("I am initing.....in dog")
class cat(Reptile):
    pass
# 实例化的时候,自动调用dog的构造函数 
# 在本类找到构造函数,则不再查找父类的构造函数
kaka = dog() 
# 在本类中没有找到构造函数,则向上父类进行查找,当在父类中找到构造函数,则查找停止
mimi = cat("mimi")


# 构造函数调用顺序 5
class A():
    def __init___(self):
        print("I am initing...in A")

class B(A):
    def __init__(self,name):
        print("I am initing....in B")
        print(name)
class C(B):
    # 扩展构造函数
    # 有两种方式 
    # 1
    """
    def __init__(self, name):
        # 首先调用父类构造函数
        B.__init__(self, name)
        # 再添加本类功能
        print("附加C功能")
    """    
    # 2
    def __init__(self, name):
        # 首先调用父类构造函数
         super(C, self).__init__(name)
        # 再添加本类功能
         print("附加C功能")        
c = C("C 本C")
# 单继承和多继承的案例
class Fish():
    def __init__(self,name):
        self.name = name
    def swim(self):
        print("{0} is swimming....".format(self.name))        
class Bird():
    def __init__(self,name):
        self.name = name
    def fly(self):
        print("{0} is flying...".format(self.name))
class Person():
    def __init__(self,name):
        self.name = name
    def work(self):
        print("{0} is working....".format(self.name))
# 多继承的例子        
class SuperMan(Person, Fish, Bird):
    def __init__(self,name):
        self.name = name        
# 单继承的例子        
class Student(Person):
    def __init__(self,name):
        self.name = name        
s = SuperMan("yueyue")
s.fly()
s.swim()
s.work()
x = Student("nana")
x.work()

6.3 多态

# Mixin 案例
class  Person():
    """
    def __init__(self,name):
        self.name = name
    """
    name = "liuyang"
    age = 18
    
    def eat(self):
        print("Eating...")
    
    def drink(self):
        print("Drinking...")
    
    def sleep(self):
        print("Sleeping...")
        
    def work(self):
        print("Working....")
class Teacher(Person):
    def teach(self):
        print("Teaching...")        
class Student(Person):
    def study(self):
        print("Studing...")        
class tutor (Teacher, Student):
    pass

t = tutor()
print(tutor.__mro__)
print(t.__dict__)
print(tutor.__dict__)
print("---" * 20)

class TeacherMixin():
    def teach(self):
        print("Teaching...")
class StudentMixin():
    def study(self):
        print("Studing...")   
class TutorMixin (Person, TeacherMixin, StudentMixin):
    pass   
 
tt = TutorMixin()
print(TutorMixin.__mro__)
print(tt.__dict__)
print(TutorMixin.__dict__)

(<class 'main.tutor'>, <class 'main.Teacher'>, <class 'main.Student'>, <class 'main.Person'>, <class 'object'>)
{}
{'module': 'main', 'doc': None}

(<class 'main.TutorMixin'>, <class 'main.Person'>, <class 'main.TeacherMixin'>, <class 'main.StudentMixin'>, <class 'object'>)
{}
{'module': 'main', 'doc': None}

7.类相关函数

8.类的成员描述符

# 属性案例 1
# 创建Student类,描述学生类
# 学生具有Student.name属性
# 但name格式并不统一
class Student():
    def __init__(self, name, age):
        self.name = name
        self.age = age       
        # 如果不想修改代码
        self.setName(name)        
    # 自我介绍函数
    def intro(self): # 此处不需要添加name,age作为参数
        print("Hi, my name is {0} and {1} years old。".format(self.name, self.age))    
    def setName(self, name):
        self.name = name.upper()        
s1 = Student("livermore", 234)
s2 = Student("wangfeng", 45)
s1.intro()
s2.intro()


# 属性案例 2
# 使用property函数
# 定义一个Person类,具有name,age属性
# 对于任意输入的名字,都用大写保存
# 年龄统一整型格式
# x = property(fget, fset, fdel, doc)
class Person():
    def fget(self):
        return self._name    
    def fset(self,name):
        # 对任意姓名都用大写保存
        self._name = name.upper()
        # 对年龄取整型保存
    #    self._age = age.int()       
    def fdel(self):
        self._name = "NOName"
        self._age = "NoAge"
    name = property(fget, fset, fdel, "对Name进行以下操作")    
 #   age = property(fget, fset, fdel, "对Age进行以下操作")     
p1 = Person()
p1.name = "calfornere "
# p1.age = 78.2
print(p1.name)
# print(p1.age)


# 类属性 property
# 应用场景
# 对变量除了普通的三种操作,还想增加一些附加的操作,那么可以通过Property完成
class A():
    def __init__(self):
        self.name = "hhaha"
        self.age = 18
    # 此功能,是对类标量进行读取操作的时候调用执行
    def fget(self):
        print("读在前面的话....")
        return self.name
    # 此功能对变量进行写操作的时候调用执行
    def fset(self,name):
        print("写在前面的话....")
        self.name = "前缀: " + name
    # 对变量进行删除操作的时候调用执行
    def fdel(self):
        pass
    
    # property 的四个参数顺序是固定的
    na = property(fget, fset, fdel, "无题")   
a = A()
print(a.name)
print(a.na

9.类的内置属性

     __dict__: 以字典的方式显示类的成员组成
     __doc__:  获取类的文档信息
     __name__: 获取类的名称,如果在模块中使用,获取模块的名称
     __bases__:获取某个类的所有父类,以元组的方式显示
# 类的内置属性 案例
print(Person.__dict__)
print(Person.__doc__)
print(Person.__name__)
print(Person.__bases__)

{'module': 'main', 'fget': <function Person.fget at 0x00000276CF9F7F70>, 'fset': <function Person.fset at 0x00000276CFA1A040>, 'fdel': <function Person.fdel at 0x00000276CFA1A0D0>, > > > > 'name': <property object at 0x00000276CFA13220>, 'age': <property object at 0x00000276CFA06E00>, 'dict': <attribute 'dict' of 'Person' objects>, 'weakref': <attribute 'weakref' > > of 'Person' objects>, 'doc': None}
None
Person
(<class 'object'>,)

10. 类的常用魔术方法

操作类

     __init__ :构造函数
     __new__ : 对象实例化方法,此函数较特殊,一般不需要使用
     __call__:  对象当函数使用的时候触发 
     __str__  : 当对象被当作字符串使用的时候触发    
     __repl__ : 返回字符串
# 操作类魔术方法
# __new__ :对象实例化方法,此函数较特殊,一般不需要使用
# __init__
# __call__ : 对象当做函数使用的时候触发
# __str__  : 当对象被当作字符串使用的时候触发
class A():
    def __init__(self):
        print("AAAAAAAAA")        
    # 当对象当作函数使用时,触发    
    def __call__(self):
        print("BBBBBBBBB")    
    # 
    def __str__(self):
        return "CCCCCCCCC"
a = A()
a()
print(a)

描述符相关

     __set__ :构造函数
     __get__ : 对象实例化方法,此函数较特殊,一般不需要使用
     __delete__:  对象当函数使用的时候触发 

属性操作相关

     __getattr__ :访问一个不存在的属性时候触发
     __setattr__ :对成员属性进行修改设置的时候触发
           - 参数: __setattr__(self, name, value)
                - self  用来获当前对象
                - name  被设置的属性名称,以字符串形式出现
                - value 需要对属性名称设置的值
           - 作用:进行属性设置的时候进行验证或修改
           - 注意:在该方法中不能对属性直接进行赋值操作,否则会死循环
# 属性操作相关魔术方法
# __getattr__
class A():
    name ="NoName"
    age = 19
    def __getattr__(self,name):
        print("查不到!")       
a = A()
print(a.name)
print(a.add)

# 为什么输出会有None???


# __setattr__ 
class P():
    def __init__(self):
        pass
    # 对Name进行修改时候触发调用
""" 
               - 参数: __setattr__(self, name, value)
                    - self  用来获当前对象
                    - name  被设置的属性名称,以字符串形式出现
                    - value 需要对属性名称设置的值
"""
    def __setattr__(self, name, value):
        print("设置属性{0}".format(value))
        # 下面语句会导致死循环
        # self.name = value \ self.name = "Noen"  
        # 为避免这种情况,规定统一调用父类魔法函数
        super().__setattr__(name,value)
p = P()        
p.name = "ddada" 

运算分类相关

     __gt__ :进行大于判断的时候触发
            - 参数
                - self
                - 第二个参数是第二个对象
                - 返回值可以任意,推荐使用布尔值 
# __gt__ 判断第一个对象是否大于第二个对象
class student():
    def __init__(self, name):
        self.name = name
     # self和obj分别代表第一个对象和第二个对象   
    def __gt__(self, obj):
        print("{0} 比 {1} 大么?".format(self.name, obj.name))
        return self.name > obj.name    
s1 = student("dididi")
s2 = student("NMNMNM")
print(s1 > s2)

# 字符串的比较大小是按照什么规则??

11. 类和对象的三种方法

# 三种方法的案例
class Person():
    # 实例方法
    def eat(self):
        print(self)
        print("Eating....") 
   
    # 类方法
    # 类方的第一个参数,一般命名为cls,区别于self
    @classmethod
    def play(cls):
        print(cls)
        print("Playing....")
        
    # 静态方法
    # 不需要用第一个参数表示自身或类
    @staticmethod
    def say():
        print("Saying...")

Dana = Person()

# 实例方法
#erson.eat()
Dana.eat()

# 类方法
Dana.play()
Dana.play()

# 静态方法
Person.say()
Dana.say()

#  关于三种方法内存使用方面的区别
# 变量的三种用法
class A():
    def __init__(self):
        self.name = "hhaha"
        self.age = 18
a = A()
# 属性的三种用法
# 赋值、读取、删除
a.name = "ouou"
a.age = 20
del a.age

12. 抽象类

# 抽象类 实例
class animal():
    # 父类定义一个函数,但没有具体的方法
    def SayHello(self):
        pass
class Dog(animal):
    # 在子类继承的时候,重新定义函数的具体方法
    def SayHello(self):
        print("闻一下")
class Person(animal):
    # 不同的子类,有不同的方法
    def SayHello(self):
        print("握一下")


# 抽象类的实现
import abc
# 声明一个类并且指定当前类的元类
class Human(metaclass=abc.ABCMeta):    
    # 定义一个抽象的方法
    @abc.abstractmethod
    def somking(self):
        pass    
    # 定义类抽象方法
    @abc.abstractclassmethod
    def drink():
        pass    
    # 定义静态抽象方法
    @abc.abstractstaticmethod
    def play():
        pass

13. 自定义类

# 组装类 实例1
class A():
    pass
def say(self):
    print("Saying....")    
say(9)
A.say = say
a = A()
a.say()


# 实例2
from types import MethodType
class B():
    pass
def talk(self):
    print("Talking....")    
b = B()
# MethodType(函数,类名)
b.talk = MethodType(talk, B)
b.talk()


# 利用type创建一个类
# 先定义类的成员函数
def say(self):
    print("Saying......")
    
def talk(self):
    print("Talking......")        
# 创建一个类
A = type("A",(object,), {"class_say":say, "class_talk":talk})
# 然后可以像正常访问一样使用类
a = A()
a.class_say()
a.class_talk()

元类演示

# 元类写法是固定的,必须继承自type
# 元类一半命名以MetaClass结尾
class TLsMetaClass(type):
    
    def __new__(cls, name, bases, attrs):
        # 方法
        print("hello......")
        attrs["id"] = "000000"
        attrs["addr"] = "北京海淀区"
        return type.__new__(cls, name, bases, attrs)    
class Teacher(object, metaclass=TLsMetaClass):
    pass
t = Teacher()
print(t.id)
print(t.addr)

类的总结:

标签:__,OPP,name,Python,self,面向对象,print,class,def
来源: https://www.cnblogs.com/rethea/p/13700275.html