zoukankan      html  css  js  c++  java
  • Python之面向对象

    1.面向对象相关的几个名词

      类:具有相同特征的一类事物。

      对象:也就是实例,具体的事物,例如动物类,那么猫就是对象,具体的实例。

      实例化:创建对象的过程,类---->对象。

    类的三要素:

      类名:类事物的名字。

      属性:类事物具体的特征。

      方法:类事物具体的行为。

    2.定义类

      类名的命名规则要符合大驼峰命名法,格式如下:

    class 类名:

      def 方法1(self,参数列表):

        pass

      def 方法2(self,参数列表):

        pass

     1 class Animal:
     2 
     3     def eat(self,name):
     4         print("%s会吃"% name)
     5 
     6     def run(self,name):
     7         print("%s会跑"% name)

    3.创建对象

      对象变量 = 类名(),调用有参数的方法即可。

     1 class Animal:
     2 
     3     def eat(self):
     4         print("会吃")
     5 
     6     def run(self):
     7         print("会跑")
     8 
     9 tom = Animal()
    10 tom.eat()
    11 tom.run()
    12 结果:
    13 会吃
    14 会跑
    View Code

    4.初始化方法

      当一个对象创建后,会自动执行以下操作:

        为对象在内存中分配空间。

        为对象的属性设置初始值。

        同时__init__方法被自动调用。

     1 class Animal:
     2 
     3     def __init__(self):
     4         self.name = "汤姆"
     5         self.age = "2岁"
     6         print("检测是否被自动调用...")
     7 
     8     def eat(self):
     9         print("会吃")
    10 
    11     def run(self):
    12         print("会跑")
    13 
    14 tom = Animal()
    15 print(tom)
    16 print(tom.name)
    17 print(tom.age)
    18 结果:
    19 检测是否被自动调用...
    20 <__main__.Animal object at 0x0000013AB6F04160>
    21 汤姆
    22 2岁
    View Code

    5.__init__方法内部定义属性

      上述定义的属性过于死板,可传入形参,此时在创建方法时直接传入属性值即可,且在对象内部可直接访问的对象的属性。

     1 class Animal:
     2 
     3     def __init__(self,name,age):
     4         self.name = name
     5         self.age = age
     6 
     7     def eat(self):
     8         print("会吃")
     9 
    10     def run(self):
    11         print("会跑")
    12 
    13 tom = Animal("汤姆","2岁")
    14 print(tom.name,tom.age)
    15 结果:
    16 汤姆 2岁
    View Code

      属性可以在类的外部设置,但是如果调用属性在设置前面,则会报错,故不建议在类的外部设置类的属性。

     1 class Animal:
     2 
     3     def __init__(self,name):
     4         self.name = name
     5 
     6     def eat(self):
     7         print("会吃")
     8 
     9     def run(self):
    10         print("会跑")
    11 
    12 tom = Animal("汤姆")
    13 print(tom.name)
    14 # print(tom.age) #结果:AttributeError: 'Animal' object has no attribute 'age'
    15 tom.age = "2岁"
    16 print(tom.age)
    17 结果:
    18 汤姆
    19 2岁
    View Code

      在对象方法内部,可以访问对象的属性。

     1 class Animal:
     2 
     3     def __init__(self,name):
     4         self.name = name
     5 
     6     def eat(self):
     7         print("%s会吃"% self.name)
     8 
     9     def run(self):
    10         print("%s会跑"% self.name)
    11 
    12 tom = Animal("汤姆")
    13 tom.eat()
    14 tom.run()
    15 结果:
    16 汤姆会吃
    17 汤姆会跑
    View Code

      同一个类创建的多个对象之间,属性互不干扰。

     1 class Animal:
     2 
     3     def __init__(self,name):
     4         self.name = name
     5 
     6     def eat(self):
     7         print("%s会吃"% self.name)
     8 
     9     def run(self):
    10         print("%s会跑"% self.name)
    11 
    12 jerry = Animal("杰瑞")
    13 tom = Animal("汤姆")
    14 tom.eat()
    15 tom.run()
    16 jerry.eat()
    17 jerry.run()
    18 结果:
    19 汤姆会吃
    20 汤姆会跑
    21 杰瑞会吃
    22 杰瑞会跑
    View Code

      一个对象的属性可以是另一个类创建的对象。

     1 class Animal:
     2 
     3     def __init__(self,name,cat_lihua):
     4         self.name = name
     5         self.cat_type = cat_lihua
     6     def eat(self):
     7         print("%s会吃"% self.name)
     8 
     9     def run(self):
    10         print("%s会跑"% self.name)
    11 
    12 class Type_cat:
    13 
    14     def __init__(self,name):
    15         self.name = name
    16 
    17     def catch(self):
    18         print("%s是%s,会抓老鼠..."%(tom.name,self.name))
    19 
    20 cat_lihua = Type_cat("狸花猫")
    21 tom = Animal("汤姆",cat_lihua)
    22 tom.cat_type.catch()
    23 结果:
    24 汤姆是狸花猫,会抓老鼠...
    View Code

    6.__del__方法

      当一个对象被从内存中销毁前,会自动调用__del__方法,del 对象名,可以删除一个对象。

     1 class Animal:
     2 
     3     def __init__(self,name):
     4         self.name = name
     5 
     6     def eat(self):
     7         print("%s会吃"% self.name)
     8 
     9     def run(self):
    10         print("%s会跑"% self.name)
    11 
    12     def __del__(self):
    13         print("检测是否有调用...")
    14 
    15 tom = Animal("汤姆")
    16 print("abc")
    17 del tom  #删除 tom对象时,立即执行了 __del__方法...
    18 print("123")
    19 结果:
    20 abc
    21 检测是否有调用...
    22 123
    View Code

      __del__是对象在生命周期内调用的最后一个方法,如果对一个对象在销毁前有需求,可以使用。

    7.__str__方法

      当print(对象名)时,默认情况下,会显示的是对象的类,以及以十六进制表示的内存中的地址,而__str__方法就是自定义print(对象名)现实的内容,此方法返回的必须是字符串。

     1 class Animal:
     2 
     3     def __init__(self,name):
     4         self.name = name
     5 
     6     def eat(self):
     7         print("%s会吃"% self.name)
     8 
     9     def run(self):
    10         print("%s会跑"% self.name)
    11 
    12     def __del__(self):
    13         print("检测是否有调用...")
    14 
    15     def __str__(self):
    16         return "检测print(对象名)是否自定义修改..."
    17 
    18 tom = Animal("汤姆")
    19 print(tom)
    20 结果:
    21 检测print(对象名)是否自定义修改...
    View Code

    8.继承

      子类继承自父类,可以直接享受父类中已经封装好的方法,不需要再次开发。

      子类中应该根据职责,封装子类特有的属性和方法。

      继承的传递性,即子类不仅拥有父类的方法和属性,还拥有父类的父类的属性和方法。

     1 class Animal:
     2 
     3     def __init__(self,name):
     4         self.name = name
     5 
     6     def eat(self):
     7         print("%s会吃"% self.name)
     8 
     9     def run(self):
    10         print("%s会跑"% self.name)
    11 
    12     def __str__(self):
    13         return "检测print(对象名)是否自定义修改..."
    14 
    15 class Cat(Animal):
    16 
    17 
    18     def catch(self):
    19         print("会抓老鼠...")
    20 
    21 tom = Cat("汤姆")
    22 tom.eat() #Cat类继承自父类Animal的方法
    23 tom.run() #Cat类继承自父类Animal的方法
    24 tom.catch() #Cat类特有方法
    25 结果:
    26 汤姆会吃
    27 汤姆会跑
    28 会抓老鼠...
    View Code

    9.方法的重写

      当父类的方法实现不能满足子类需求时,可以对方法进行重写。

     1 class Animal:
     2 
     3     def __init__(self,name):
     4         self.name = name
     5 
     6     def eat(self):
     7         print("%s会吃"% self.name)
     8 
     9     def run(self):
    10         print("%s会跑"% self.name)
    11 
    12 
    13 class Cat(Animal):
    14 
    15     def catch(self):
    16         print("会抓老鼠...")
    17 
    18     def eat(self):
    19         print("%s吃鱼"% tom.name)
    20 
    21 tom = Cat("汤姆")
    22 tom.eat()
    23 结果:
    24 汤姆吃鱼
    View Code

      当父类的方法同样有需求,但还有其他需求时,可调用父类的方法的同时,再进行扩展。

     1 class Animal:
     2 
     3     def __init__(self,name):
     4         self.name = name
     5 
     6     def eat(self):
     7         print("%s会吃"% self.name)
     8 
     9     def run(self):
    10         print("%s会跑"% self.name)
    11 
    12 
    13 class Cat(Animal):
    14 
    15     def catch(self):
    16         print("会抓老鼠...")
    17 
    18     def eat(self):
    19         super().eat()
    20         print("%s吃鱼"% tom.name)
    21 
    22 tom = Cat("汤姆")
    23 tom.eat()
    24 结果:
    25 汤姆会吃
    26 汤姆吃鱼
    View Code

    10.私有属性和方法

      私有属性、方法就是对象不希望公开的属性、方法,在属性名和方法名前加两个下划线,定义的就是私有属性或方法,在类的外部无法访问,在对象的方法内部可以访问。

     1 class Animal:
     2 
     3     def __init__(self,name,age):
     4         self.name = name
     5         self.__age = age
     6 
     7     def eat(self):
     8         print("%s会吃"% self.name)
     9 
    10     def __run(self):
    11         print("%s会跑"% self.name)
    12 
    13 tom = Animal("汤姆","2岁")
    14 print(tom.name)
    15 # print(tom.age) #结果:AttributeError: 'Animal' object has no attribute 'age'
    16 tom.eat()
    17 # tom.run() #结果:AttributeError: 'Animal' object has no attribute 'run'
    18 结果:
    19 汤姆
    20 汤姆会吃
    View Code

      子类对象不能在自己的方法内部,直接访问父类的私有属性或方法,可以在自己的内部访问父类的共有属性和公有方法。

     1 class Animal:
     2 
     3     def __init__(self,name,age):
     4         self.name = name
     5         self.__age = age
     6 
     7     def eat(self):
     8         print("%s会吃"% self.name)
     9 
    10     def __run(self):
    11         print("%s会跑"% self.name)
    12 
    13 class Cat(Animal):
    14 
    15     def catch(self):
    16         print("%s是狸花猫..."% self.name)
    17         # print("%s%s了"%(self.name,self.age)) #结果:AttributeError: 'Cat' object has no attribute 'age'
    18 
    19 tom = Cat("汤姆","2岁")
    20 tom.catch()
    21 tom.eat()
    22 # tom.__run() #结果:AttributeError: 'Cat' object has no attribute '__run'
    23 结果:
    24 汤姆是狸花猫...
    25 汤姆会吃
    View Code

      父类内部可以调用自己的私有属性和方法,子类可以调用父类的公有属性和方法,所以我们可以间接调用父类的私有属性和方法。即我们在父类的公有方法中调用其私有方法,子类中调用父类公有方法,从而达到调用父类私有方法的目的。

     1 class Animal:
     2 
     3     def __init__(self,name,age):
     4         self.name = name
     5         self.__age = age
     6 
     7     def eat(self):
     8         print("%s会吃"% self.name)
     9 
    10     def __run(self):
    11         print("%s会跑"% self.name)
    12 
    13     def run(self):
    14         self.__run()
    15         print("%s%s了"%(self.name,self.__age))
    16 
    17 
    18 class Cat(Animal):
    19 
    20     def catch(self):
    21         print("%s是狸花猫..."% self.name)
    22 
    23 tom = Cat("汤姆","2岁")
    24 tom.run()
    25 结果:
    26 汤姆会跑
    27 汤姆2岁了
    View Code

    11.多继承

      子类可以拥有多个父类,并且具有所有父类的属性和方法,尽量避免父类之间出现同名的属性和方法。

     1 class A:
     2 
     3     def foo(self):
     4         print("fool A...")
     5 
     6     def bar(self):
     7         print("bar A...")
     8 
     9 
    10 class B:
    11 
    12     def foo(self):
    13         print("fool B...")
    14 
    15     def bar(self):
    16         print("bar B...")
    17 
    18 
    19 class C(A,B):
    20     pass
    21 
    22 cc = C()
    23 cc.foo()
    24 cc.bar()
    25 结果:
    26 fool A...
    27 bar A...
    28 
    29 
    30 ----------分割线-----------
    31 class A:
    32 
    33     def foo(self):
    34         print("fool A...")
    35 
    36     def bar(self):
    37         print("bar A...")
    38 
    39 
    40 class B:
    41 
    42     def foo(self):
    43         print("fool B...")
    44 
    45     def bar(self):
    46         print("bar B...")
    47 
    48 
    49 class C(B,A):
    50     pass
    51 
    52 cc = C()
    53 cc.foo()
    54 cc.bar()
    55 结果:
    56 fool B...
    57 bar B...
    View Code

      当拥有多个父类,且具有相同方法和属性时,调用时不易区分调用的是哪个父类的方法,可用__mro__方法搜素查找调用父类方法的顺序。

    12.新式类和经典类

      新式类:以object为基类的是新式类,具有object类的内置封装的方法,推荐使用。
      经典类:不以object为基类的类。

    13.多态

      不同的子类对象调用相同的父类方法,产生不同的执行结果,多态是以继承和重写父类方法为前提下,同一个方法会产生不同的形态。

    14.类属性

      在类中定义属性,通常用来记录与类有关的特征,类属性不会记录具体对象的特征。

    有两种访问方法:

      类名.属性名

      对象名.属性名  (不推荐使用)

     1 class Animal:
     2     count = 0
     3 
     4     def __init__(self,name,age):
     5         self.name = name
     6         self.age = age
     7         Animal.count += 1
     8 
     9     def eat(self):
    10         print("%s贼贪吃..."% self.name)
    11 
    12 dog = Animal("金毛","1岁")
    13 cat = Animal("汤姆","2岁")
    14 print(Animal.count)
    15 print(dog.count)
    16 print(cat.count)
    17 结果:
    18 2
    19 2
    20 2
    View Code

      两种方法仅仅访问时,都能达到效果。但是当用 对象名.属性名 访问方法给类属性赋值时,会在对象中重新创建一个与类属性名相同的 对象属性,并且将值赋予对象属性,故不推荐使用。

     1 class Animal:
     2     count = 0
     3 
     4     def __init__(self,name,age):
     5         self.name = name
     6         self.age = age
     7         Animal.count += 1
     8 
     9     def eat(self):
    10         print("%s贼贪吃..."% self.name)
    11 
    12 dog = Animal("金毛","1岁")
    13 cat = Animal("汤姆","2岁")
    14 cat.count = 10
    15 print(Animal.count)
    16 print(dog.count)
    17 print(cat.count)
    18 结果:
    19 2
    20 2
    21 10
    View Code

    15.类方法

      如果一个方法内部值需要访问类属性时,即可定义成类方法。

    语法格式:

    @classmethod

    def 类方法名(cls):

      pass

     1 class Animal:
     2     count = 0
     3 
     4     def __init__(self,name,age):
     5         self.name = name
     6         self.age = age
     7         Animal.count += 1
     8 
     9     def eat(self):
    10         print("%s贼贪吃..."% self.name)
    11 
    12     @classmethod
    13     def obj_num(cls):
    14         print("创建的对象数:%s"%Animal.count)
    15 
    16 dog = Animal("金毛","1岁")
    17 cat = Animal("汤姆","2岁")
    18 Animal.obj_num()
    19 cat.obj_num()
    20 结果:
    21 创建的对象数:2
    22 创建的对象数:2
    View Code

    16.静态方法

      如果一个方法内部既不需要访问实例属性或者调用实例方法,也不需要访问类属性或者调用类方法,此时,可以把这个方法封装成一个静态方法。

    @staticmethod

    def 静态方法():

      pass

      调用静态方法时不用创建对象,通过 类名.静态方法名() 调用即可。

     1 class Animal:
     2     count = 0
     3 
     4     def __init__(self,name,age):
     5         self.name = name
     6         self.age = age
     7         Animal.count += 1
     8 
     9     def eat(self):
    10         print("%s贼贪吃..."% self.name)
    11 
    12     @classmethod
    13     def obj_num(cls):
    14         print("创建的对象数:%s"%cls.count)
    15 
    16     @staticmethod
    17     def fun():
    18         print("静态方法...")
    19 
    20 Animal.fun()
    21 结果:
    22 静态方法...
    View Code

    17.单例模式

      目的:让类在创建对象时,系统中只存在唯一的一个实例,即每次执行时,返回对象的地址都是相同的。

      正常情况,每创建一个对象,其地址都是不同的。

     1 class Animal:
     2 
     3     def __init__(self,name,age):
     4         self.name = name
     5         self.age = age
     6 
     7 cat = Animal("汤姆","2岁")
     8 dog = Animal("二哈","1岁")
     9 print(cat)
    10 print(dog)
    11 结果:
    12 <__main__.Animal object at 0x000001C3BDAA9550>
    13 <__main__.Animal object at 0x000001C3BDAB42B0>
    View Code

    1)__new__方法

      我们知道,当创建一个对象时,python解释器会自动执行两个方法,__new__方法为对象分配空间,__init__方法初始化对象。

      __new__方法是一个静态方法,为对象在内存中分配空间,并且返回对象的引用。

    2)重写__new__方法

      重写时,要调用父类方法,赋值给一个变量,再将变量返回。固定的代码。

    1 instance = None
    2 def __new__(cls, *args, ""kwargs):
    3     if isstance is None:
    4         cls.instance = super().__new__(cls)
    5     return cls.instance
     1 class Animal:
     2 
     3     def __init__(self,name,age):
     4         self.name = name
     5         self.age = age
     6         print("检测__init__方法调用次数...")
     7 
     8     instance = None
     9 
    10     def __new__(cls, *args, **kwargs):
    11         if cls.instance is None:
    12             cls.instance = super().__new__(cls)
    13         return cls.instance
    14 
    15 cat = Animal("汤姆","2岁")
    16 dog = Animal("二哈","1岁")
    17 print(cat)
    18 print(dog)
    19 结果:
    20 检测__init__方法调用次数...
    21 检测__init__方法调用次数...
    22 <__main__.Animal object at 0x0000021187C84160>
    23 <__main__.Animal object at 0x0000021187C84160>
    View Code

      重写__new__方法后,不管创建多少个对象,返回的地址都是创建的第一个对象的地址,但是__init__方法每创建一个对象会初始化一次。我们可以设置一个 类属性,将False 赋值给他,然后在__init__方法内用if判断,如果为False则执行初始化方法,执行后将类属性的值改为True,再次调用__init__方法时就不会被多次执行。

     1 class Animal:
     2 
     3     init_fun = False
     4 
     5     def __init__(self,name,age):
     6         if Animal.init_fun is False:
     7             self.name = name
     8             self.age = age
     9             print("检测__init__方法调用次数...")
    10             Animal.init_fun = True
    11         return
    12 
    13     instance = None
    14 
    15     def __new__(cls, *args, **kwargs):
    16         if cls.instance is None:
    17             cls.instance = super().__new__(cls)
    18         return cls.instance
    19 
    20 cat = Animal("汤姆","2岁")
    21 dog = Animal("二哈","1岁")
    22 print(cat)
    23 print(dog)
    24 结果:
    25 检测__init__方法调用次数...
    26 <__main__.Animal object at 0x0000022EA09742B0>
    27 <__main__.Animal object at 0x0000022EA09742B0>
    View Code

    18.异常

      抛出异常:程序执行时遇到一个错误,会停止程序的执行,并且提示一些错误信息。

     1 try:
     2     pass
     3 except 异常类型1:
     4     pass
     5 except 异常类型2:
     6     pass
     7 except Excetion as e:
     8     print("未知错误,%s",%e)
     9 else: #没有出现异常才会执行的代码
    10     pass
    11 finally:  #无论是否有异常,都会执行的代码
    12     pass

      异常类型为触发异常后抛出的异常信息中的第一个单词,用以捕捉异常。

     1 try:
     2     int_put = int(input("输入数字>>>"))
     3     num = 10 / int_put
     4     print(num)
     5 except ValueError:
     6     print("输入错误的值,请输入数字>>>")
     7 except ZeroDivisionError:
     8     print("除数为0错误...")
     9 except Exception as e:
    10     print("未知错误,%s"%e)
    11 else:
    12     print("没有出现异常才会执行的代码")
    13 finally:
    14     print("无论是否有异常,都会执行的代码")
    15 结果:
    16 输入数字>>>10
    17 1.0
    18 没有出现异常才会执行的代码
    19 无论是否有异常,都会执行的代码
    20 
    21 ------------结果分割线
    22 
    23 结果:
    24 输入数字>>>0
    25 除数为0错误...
    26 无论是否有异常,都会执行的代码
    View Code

    1)异常的传递

      为了让程序能够正常运行,方法中都应该有异常处理,但是如果每个方法都写入异常处理的代码,太繁琐。事实上,当函数/方法执行 出现异常,会将异常传递给函数/方法的调用一方,如果传递到主程序,仍然没有异常处理,程序才会被终止。即异常具有传递性,所以,当我们再主程序中增加异常处理,就不用每个方法中都增加。

    2)主动抛出异常

      根据业务需求,会有主动抛出异常的情况,python中提供了Exception类。

    1 ex = Exception("xx错误") #创建异常对象,括号内可以用错误信息作为参数
    2 raise ex #主动抛出异常

      主动抛出异常类似于执行了错误代码,要与捕捉异常一起使用。

  • 相关阅读:
    array_map()与array_shift()搭配使用 PK array_column()函数
    Educational Codeforces Round 8 D. Magic Numbers
    hdu 1171 Big Event in HDU
    hdu 2844 poj 1742 Coins
    hdu 3591 The trouble of Xiaoqian
    hdu 2079 选课时间
    hdu 2191 珍惜现在,感恩生活 多重背包入门题
    hdu 5429 Geometric Progression 高精度浮点数(java版本)
    【BZOJ】1002: [FJOI2007]轮状病毒 递推+高精度
    hdu::1002 A + B Problem II
  • 原文地址:https://www.cnblogs.com/foxshu/p/12156474.html
Copyright © 2011-2022 走看看