0x013.Python learning-object-oriented

 

Python3 object-oriented

Not much to say, let’s get a bunch of theoretical knowledge first, just use ctrl+F

Python has been an object-oriented language since its design. Because of this, it is easy to create a class and object in Python. In this chapter, we will introduce Python's object-oriented programming in detail.

If you have not been exposed to object-oriented programming languages ​​before, you may need to understand some of the basic features of object-oriented languages ​​and form a basic object-oriented concept in your mind, which will help you learn Python more easily. Object-Oriented Programming.

Next, let's briefly understand some of the basic characteristics of the following object.


Introduction to Object-Oriented Technology

  • Class:  Used to describe a collection of objects with the same properties and methods. It defines the attributes and methods common to each object in the collection. Objects are instances of classes.
  • Method: The function defined in the class.
  • Class variables: Class variables are common in the entire instantiated object. Class variables are defined in the class and outside the function body. Class variables are usually not used as instance variables.
  • Data members: class variables or instance variables are used to process data related to the class and its instance objects.
  • Method rewriting: If the method inherited from the parent class cannot meet the needs of the child class, it can be rewritten. This process is called method override, also known as method rewriting.
  • Local variable: The variable defined in the method only acts on the class of the current instance.
  • Instance variables: In the declaration of a class, attributes are represented by variables. Such variables are called instance variables, which are declared inside the class declaration but outside of the other member methods of the class.
  • Inheritance: That is, a derived class inherits the fields and methods of the base class. Inheritance also allows an object of a derived class to be treated as a base class object. For example, there is such a design: an object of type Dog is derived from the Animal class, which simulates the "is-a" relationship (example diagram, Dog is an Animal).
  • Instantiation: Create an instance of a class, a specific object of the class.
  • Object: An instance of a data structure defined by a class. The object includes two data members (class variables and instance variables) and methods.

Compared with other programming languages, Python adds a class mechanism without adding new syntax and semantics as much as possible.

Classes in Python provide all the basic functions of object-oriented programming: the inheritance mechanism of classes allows multiple base classes, derived classes can cover any method in the base class, and methods of the same name in the base class can be called in the method.

Objects can contain any amount and type of data.

Class-specific methods:

  • __init__:  Constructor, called when the object is generated
  • __del__:  Destructor, used when releasing the object
  • __repr__:  print, convert
  • __setitem__:  Assign value according to index
  • __getitem__:  Get the value according to the index
  • __len__:  get the length
  • __cmp__:  comparison operation
  • __call__:  function call
  • __add__:  addition operation
  • __sub__:  subtraction operation
  • __mul__:  Multiplication
  • __truediv__:  division operation
  • __mod__:  remainder operation
  • __pow__:  power
针对 __str__ 方法给出一个比较直观的例子:
class people:
    def __init__(self,name,age):
        self.name=name
        self.age=age

    def __str__(self):
        return '这个人的名字是%s,已经有%d岁了!'%(self.name,self.age)

a=people('孙悟空',999)
print(a)
输出:
这个人的名字是孙悟空,已经有999岁了!
如果没有重载函数的话输出的就是一串看不懂的字符串:
<__main__.people object at 0x00000272A730D278>
最新的 Python3.7 中(2018.07.13),对类的构造函数进行了精简。
3.7 版本:
from dataclasses import dataclass
@dataclass
class A:
  x:int
  y:int
  def add(self):
    return self.x + self.y
相当于以前的:
class A:
  def __init__(self,x,y):
    self.x = x
    self.y = y
  def add(self):
    return self.x + self.y
静态方法: 用 @staticmethod 装饰的不带 self 参数的方法叫做静态方法,类的静态方法可以没有参数,可以直接使用类名调用。
普通方法: 默认有个self参数,且只能被对象调用。
类方法: 默认有个 cls 参数,可以被类和对象调用,需要加上 @classmethod 装饰器。
class Classname:
    @staticmethod
    def fun():
        print('静态方法')

    @classmethod
    def a(cls):
        print('类方法')

    # 普通方法
    def b(self):
        print('普通方法')



Classname.fun()
Classname.a()

C = Classname()
C.fun()
C.a()
C.b()
selfeasy
   selfeasy



反向运算符重载:
__radd__: 加运算
__rsub__: 减运算
__rmul__: 乘运算
__rdiv__: 除运算
__rmod__: 求余运算
__rpow__: 乘方
复合重载运算符:
__iadd__: 加运算
__isub__: 减运算
__imul__: 乘运算
__idiv__: 除运算
__imod__: 求余运算
__ipow__: 乘方
运算符重载的时候:
#!/usr/bin/python3

class Vector:
    def __init__(self, a, b):
        self.a = a
        self.b = b
    def __str__(self):
        return 'Vector (%d, %d)' % (self.a, self.b)

    def __repr__(self):
        return 'Vector (%d, %d)' % (self.a, self.b)

    def __add__(self,other):
        if other.__class__ is Vector:
            return Vector(self.a + other.a, self.b + other.b)
        elif other.__class__ is int:
            return Vector(self.a+other,self.b)

    def __radd__(self,other):
        """反向算术运算符的重载
        __add__运算符重载可以保证V+int的情况下不会报错,但是反过来int+V就会报错,通过反向运算符重载可以解决此问题
        """

        if other.__class__ is int or other.__class__ is float:
            return Vector(self.a+other,self.b)
        else:
            raise ValueError("值错误")

    def __iadd__(self,other):
        """复合赋值算数运算符的重载
        主要用于列表,例如L1+=L2,默认情况下调用__add__,会生成一个新的列表,
        当数据过大的时候会影响效率,而此函数可以重载+=,使L2直接增加到L1后面
        """

        if other.__class__ is Vector:
            return Vector(self.a + other.a, self.b + other.b)
        elif other.__class__ is int:
            return Vector(self.a+other,self.b)
v1 = Vector(2,10)
v2 = Vector(5,-2)
print (v1 + v2)
print (v1+5)
print (6+v2)
Python3 类方法总结
 普通方法:对象访问
 私有方法:两个下划线开头,只能在类内部访问
 静态方法:类和对象访问,不能和其他方法重名,不然会相互覆盖,后面定义的会覆盖前面的
 类方法:类和对象访问,不能和其他方法重名,不然会相互覆盖,后面定义的会覆盖前面的
 多继承情况下:从左到右查找方法,找到为止,不然就抛出异常
class People:

    # 定义基本属性
    name=''
    age=0
    # 定义私有属性外部无法直接访问
    __weight=0
    def __init__(self,n,a,w):
        self.name = n
        self.age = a
        self.__weight = w
    def speak(self):
        print("%s say : i am %d."%(self.name,self.age))
p = People('Python',10,20)
p.speak()
# __weight无法直接访问
print(p.name,'--',p.age)#,'--',p.__weight)
继承
单继承:
class Student(People):
    grade=''
    def __init__(self,n,a,w,g):
        People.__init__(self,n,a,w)
        self.grade = g

    # 覆写父类方法
    def speak():
        print("%s 说: 我 %d 岁了,我在读 %d 年级"%(self.name,self.age,self.grade))

class Speak():
    topic=''
    name=''
    def __init__(self,n,t):
        self.name = n
        self.topic = t
    # 普通方法,对象调用
    def speak(self):
        print("我叫 %s,我是一个演说家,我演讲的主题是 %s"%(self.name,self.topic))

    # 私有方法,self调用
    def __song(self):
        print('唱一首歌自己听',self);

    # 静态方法,对象和类调用,不能和其他方法重名,不然会相互覆盖,后面定义的会覆盖前面的
    @staticmethod
    def song():
        print('唱一首歌给类听:静态方法');

    # 普通方法,对象调用
    def song(self):
        print('唱一首歌给你们听',self);
        
    # 类方法,对象和类调用,不能和其他方法重名,不然会相互覆盖,后面定义的会覆盖前面的
    @classmethod
    def song(self):
        print('唱一首歌给类听:类方法',self)
多继承:
class Sample(Speak,Student):
    a = ''
    def __init__(self,n,a,w,g,t):
        Student.__init__(self,n,a,w,g)
        Speak.__init__(self,n,t)
test = Sample('Song',24,56,7,'Python')
test.speak()
test.song()
Sample.song()
Sample.song()
test.song()

# test.__song() 无法访问私有方法
类的二元方法运算符重载介绍的并不全面,文中介绍的全是正向方法,其实还有反向方法,就地方法。下面补充一些。
当解释器碰到 a+b 时,会做以下事情:
从 a 类中找 __add__ 若返回值不是 NotImplemented, 则调用 a.__add__(b)。
若 a 类中没有 __add__ 方法,则检查 b 有没有 __radd__ 。如果如果有,则调用 b.__radd__(a),若没有,则返回 NotImplemented。
接上条,若 b 也没有 __radd__ 方法,则抛出 TypeError,在错误消息中知名操作数类型不支持。
比如:向量类 <Myvector> 应当有向量与整数的乘法:
>>>a = Myvector([1,2,3])
>>>print(a.value)
[1,2,3]
>>>b=3
>>>c = a*b   #此时调用Myvector.__mul__()
>>>print(c.value)
[3,6,9]
>>> d=b*a  #这句会出错。
期望得到 b*a 也返回一个向量,b*a 应该等于 a*b。此时就需要在 Myvector 类中定义一个__rmul__方法。
def __rmul__(self, other):
    if isinstance(other, int):
        return Myvector([a*other for a in self.m])
每个运算符都有正向方法重载,反向方法重载。有一些有就地方法(即不返回新的对象,而是修改原本对象)。

 

 

class Ren:
    name ="zhangsan"
    age =20
    sex ='man'
    def run(self):
        print 'basketball'

class Ren:
    name ="zhangsan"      #变量
    age =20
    sex ='man'
    def run(self,x):        #函数
        print 'basketball'
        print x
zhang =Ren()                  #创建对象的过程叫实例化,zhang为对象
print zhang.name
zhang.run('xxxxxxxxxx')       #对象的方法
zhang.age =40                 #设置属性
print zhang.age
zhang.job ='it'               #添加属性
print zhang.job

 

class Ren:
    name ="zhangsan"      #变量
    age =20
    sex ='man'
    __tt ='zs'
    def run(self,x):        #函数
        print 'basketball'
        print x
        print self.__tt       #内部调用私有属性
zhang =Ren()                  
print zhang.name
zhang.run('xxxxxxxxxx')     
zhang.age =40                 
print zhang.age
zhang.job ='it'               
print zhang.job
print zhang._Ren__tt          #调用内部私有类

 

#! /usr/bin/python
# ! -*- coding: UTF-8 -*-

class Ren:
    name = "zhangsan"  # 变量
    age = 20
    sex = 'man'
    __tt = 'zs'

    def run(self, x):  # 函数
        print 'basketball'
        print x
        print self.__tt  # 内部调用私有属性

    def __kk(self, x):  # 函数
        print 'running'
        print self.__tt  # 内部调用私有属性

    @classmethod #函数修饰符 或者声明称静态函数@staticmethod,静态函数就不需要加参数了,即无须self
    def hel(self): #@classmethod 相当于把run函数加载到classmethod里面运行,即run =@classmethod(run)
        print "hel man!"  # 使用私有方法进行调用测试


zhang = Ren()  # 创建对象的过程叫实例化,zhang为对象
print zhang.name
zhang.run('xxxxxxxxxx')  # 对象的方法
zhang.age = 40  # 设置属性
print zhang.age
zhang.job = 'it'  # 添加属性
print zhang.job
print zhang._Ren__tt  # 调用内部私有类
zhang._Ren__kk("私有方法调用")
zhang.hel()  # 公有方法
Ren.hel()    #私有方法调用

 

 

 

class Ren:

    class Badren: #Internal class
        name ='huairen'
        @classmethod
        def badshi(self):
            print'papapa'
huairen =Ren.Badren #Instantiate the internal class
print huairen.name #On the variables in the internal class Call
huairen.badshi() #

class Ren:
    def __init__(self,x):
        print'Constructor: When instantiating an object, the constructor will be executed by default, that is, when instantiating, first call the constructor
        ' print'xxxxxxxxxx:',x # When instantiating an object, pass parameters to it and implement it through the constructor
zhang =Ren("zhangsan")#When instantiating an object, pass parameters to it, implement

#f =open('c:\ 1.txt','r') #In a read-only form, instantiate function f, file operations

class Ren:
    name = "zhangsan"  # 变量
    age = 20
    sex = 'man'
    __tt = 'zs'
    def __del__(self): #析构函数
        f = open('c:\1.txt', 'r')
        f.read()
        f.close()

 

 

class Parent:
    name ='lisi'
    parentAttr = 100
    def fulei(self):
        print '这是父类中的方法'
    def __init__(self):
        print "这是父类中构造函数,私有化方法"
class Child(Parent):#子类调用父类
    name ='lisi'
    def childMethod(self):
        print '这是子类中的方法'
child =Child()#实例化子类
child.fulei()#子类调用父类中的方法
child.childMethod()#调用子类中本身的方法
print child.name #(子类父类中同有的变量),子类调用时,优先权会高于父类,输出lisi 

Lession13 total code:

#! /usr/bin/python
# ! -*- coding: UTF-8 -*-
#【继承】
#父类有的,继承后子类可以直接调用
#父类子类都有同一个重名函数,优先子类调用自己的
#父类只能调用自己的函数
class Ren:
    name = "zhangsan"  # 变量
    age = 20
    sex = 'man'
    __tt = 'zs'
    def __del__(self): #析构函数
        f = open('c:\1.txt', 'r')
        f.read()
        f.close()
'''
    def __init__(self,x):
        print '构造函数:当实例化对象的时候,构造函数就会被默认执行,即实例化的时候,先调用构造函数'
        print 'xxxxxxxxxx:',x #实例化对象的时候,对其进行传参,通过构造函数实现
zhang =Ren("zhangsan")#实例化对象的时候,对其进行传参,通过构造函数实现

#f =open('c:\1.txt','r') #以只读的形式,实例化函数f ,文件操作


     def run(self, x):  # 函数
        print 'basketball'
        print x
        print self.__tt  # 内部调用私有属性

    def __kk(self, x):  # 函数
        print 'running'
        print self.__tt  # 内部调用私有属性

    @classmethod #函数修饰符 或者声明称静态函数@staticmethod,静态函数就不需要加参数了,即无须self
    def hel(self): #@classmethod 相当于把run函数加载到classmethod里面运行,即run =@classmethod(run)
        print "hel man!"  # 使用私有方法进行调用测试

    class Badren: #内部类
        name ='huairen'
        @classmethod
        def badshi(self):
            print 'papapa'


zhang = Ren()  # 创建对象的过程叫实例化,zhang为对象
print zhang.name
zhang.run('xxxxxxxxxx')  # 对象的方法
zhang.age = 40  # 设置属性
print zhang.age
zhang.job = 'it'  # 添加属性
print zhang.job
print zhang._Ren__tt  # 调用内部私有类
zhang._Ren__kk("私有方法调用")
zhang.hel()  # 公有方法
Ren.hel()    #私有方法调用
huairen =Ren.Badren #对内部类进行实例化 或者是huairen=zhang.Badren
print huairen.name #对内部类里面的变量进行调用
huairen.badshi() #对内部类的方法进行调用
'''
class Parent:
    name ='lisi'
    parentAttr = 100
    def fulei(self):
        print '这是父类中的方法'
    def __init__(self):
        print "这是父类中构造函数,私有化方法"
class Child(Parent):#子类调用父类
    name ='lisi'
    def childMethod(self):
        print '这是子类中的方法'
child =Child()#实例化子类
child.fulei()#子类调用父类中的方法
child.childMethod()#调用子类中本身的方法
print child.name #(子类父类中同有的变量),子类调用时,优先权会高于父类,输出lisi
class sson(Child):
    print '我是孙子类,测试能否继承爷爷类'
sson =sson()#并且实例化对象时,会再次加载构造函数
sson.fulei()# 结果测试可以继承

Please indicate: Adminxe's Blog  »  0x013. Python learning-object-oriented

Guess you like

Origin blog.csdn.net/Adminxe/article/details/106679052