NMT Data Mining & Big Data

面向对象编程(OOP)之系列1

2019-06-06
NMt

面向对象编程概述、实例对象属性、类对象属性

@@@@

本文是来源于上雷俊丽老师python课的课件。

1.面向对象编程概述

面向对象编程(OOP), 是一种编程方式,这种编程方式需要使用“对象”来实现。

对象的特征:

  1. 世间万物皆对象。
  2. 每个对象都是唯一的。
  3. 对象具有属性和行为。
  4. 对象具有状态。
  5. 对象分为类对象和实例对象两大类。

面向对象编程的大体步骤:

  1. 抽象出类对象。
  2. 抽象出类对象的属性。
  3. 抽象出类对象的行为(方法)。
  4. 根据类对象创建实例对象。
  5. 通过实例对象访问属性和方法。

定义类对象的语法格式:

class name(object):
    #property and function.

其中:

  1. 类名由一个或多个单词组合而成,每个单词的首字母大写且其余字母全部小写,例如:SomeClass。
  2. (object)表示该类对象继承自Python内置的类对象object,Python中所有的类对象都继承自一个统一的基类:object。

实例化:

cat = Cat('傻猫', 'wang', 1, 'good')

属性:

  1. 为了在创建实例对象后对其进行初始化(例如:给实例对象绑定一些属性),可以在类对象中定义一个名为__init__的特殊方法(以双下划线__开头和结尾的方法)。这样,创建实例对象后就会自动调用特殊方法__init__
  2. 如果没有定义特殊方法__init__, 或者定义了特殊方法__init__但是没有定义除self之外的形参,那么根据类对象创建实例对象时就不需要传入实参。
  3. 如果在类对象中定义了特殊方法__init__, 那么对于“类名([实参])”,会执行两大步:
    1. 创建实例对象
    2. 会自动调暗勇创建的实例对象的特殊方法__init__(创建的实例对象会作为实参被自动传递给特殊方法__init__的第一个形参self)。

类的方法与函数的区别:

方法就是定义在类对象中的函数。方法与函数的区别在于:

  1. 定义方法时,方法的第一个形参表示调用该方法的实例对象,第一个形参的名称通常时self,也可以是其他名称。
  2. 调用方法时,系统自动将调用该方法的实例对象作为实参传递给第一个形参。第一个实参会传递给第二个形参,第二个实参会传递给第三形参,依次类推。

根据类对象创建实例对象的语法格式为:
类名([实参])

class Cat(object):
    def __init__(self, breed, name, age, health):
        self.breed = breed
        self.name = name
        self.age = age
        self.health = health
        #猫具有的属性:品质拍卖会、昵称、年龄、健康状况
        #self指实例化的对象,将属性赋给实例化的对象
        #self表示自己,可以取其他的名字,但一般不取其他名字
        #实例对象取cls
        #后面四个都需要赋值,self不需要传参数
        
    def run(self):
        print('run')

    def miao(self):
        print('miao')

    def eat(self):
        print('eat')
    #实例对象公共的行为方法定义为函数。
    #猫将原有的行为:跑、叫、吃

#实例化
cat = Cat('傻猫', 'wang', 1, 'good')

#查看对象的属性
print(cat.breed)
print(cat.name)
print(cat.age)
print(cat.health)

[out]
傻猫
wang
1
good

#调用方法(类里面定义的函数)
cat.run()
cat.miao()
cat.eat()

[out]
run
miao
eat

2.实例对象属性

实例属性:

实例属性指的是实例对象所绑定的属性。
绑定实例属性(给实例对象绑定属性)的方式有两种:

  1. 在类对象的内部(方法中)
    语法格式:self.property = value
    推荐在特殊方法__init__中进行绑定,这样,在创建实例对象后就会自动调用特殊方法__init__对实例对象进行初始化,从而绑定实例属性。如果在其他方法中进行绑定,可能需要手动调用方法后才会绑定。
  2. 在类对象的外部
    Python时动态语言,所以,在实例对象创建之后,可以对其动态地绑定属性。
    语法格式:实例对象.属性名 = 属性值
    如果指定名称地实例属性已经存在,则是对实例属性进行修改。

访问实例属性地方式有两种:

  1. 在类对象的内部(方法中)
    语法格式:self.property
  2. 在类对象的外部
    语法格式:实例对象.属性名

之所以添加前缀“self”或“实例对象”,是为了表明实例属性被哪个实例对象所绑定。

class MyClass(object):
    def __init__(self):
        #在类对象的内部(方法中)绑定实例属性
        self.ia1 = 18
    
    def do_sth1(self):
        #在类对象的内部(方法中)访问实例属性
        print(self.ia1)
    
    def do_sth2(self):
        print(self.ia2)
    
    def do_another(self):
        #在类对象的内部(方法中)绑定实例属性
        self.ia2 = 56
    
    def do_sth3(self):
        print(self.ia3)

mc = MyClass()
mc.do_sth1()

[out]
18

mc.do_another()
mc.do_sth2()

[out]
56

#在类的外部定义属性
mc.ia3 = 66
mc.do_sth3()

[out]
66

mc2 = MyClass()
print(mc2.ia3)

[out]
---------------------------------------------------------------------------
AttributeError                            Traceback (most recent call last)
<ipython-input-34-85d88b23cdb9> in <module>
      1 mc2 = MyClass()
----> 2 print(mc2.ia3)
      3 #同一个类对象的。。。(除非是公共属性)

AttributeError: 'MyClass' object has no attribute 'ia3'

同一个类对象的不同实例对象所绑定的实例属性是相互独立的。也就是说,给一个实例对象所绑定的实例属性,对于另外一个实例对象是不起作用的。

实例对象.__dict__
可获得该实例对象所绑定的所有属性及其值的字典。

#实例对象.__dict__
#可获得该实例对象所绑定的所有属性及其值的字典
mc.__dict__
mc2.__dict__

[out]
{'ia1': 18}

[out]
['__class__',
 '__delattr__',
 '__dict__',
 '__dir__',
 '__doc__',
 '__eq__',
 '__format__',
 '__ge__',
 '__getattribute__',
 '__gt__',
 '__hash__',
 '__init__',
 '__init_subclass__',
 '__le__',
 '__lt__',
 '__module__',
 '__ne__',
 '__new__',
 '__reduce__',
 '__reduce_ex__',
 '__repr__',
 '__setattr__',
 '__sizeof__',
 '__str__',
 '__subclasshook__',
 '__weakref__',
 'do_another',
 'do_sth1',
 'do_sth2',
 'do_sth3',
 'ia1']

3.类对象属性

类属性
类属性指的是类对象所绑定的属性。

绑定类属性(给类对象绑定属性)的方式有两种:

  1. 在类对象的内部(方法外)
    语法格式:属性名 = 属性值
  2. 在类对象的外部
    Python是动态语言,所以在类对象创建之后,可以对其动态地绑定属性。
    语法格式:类对象.属性名 = 属性值 如果指定名称的类属性已经存在,则是对类属性进行修改。

访问类属性的方式有两种:

  1. 在类对象的内部(方法中)
    语法格式:类对象.属性名
  2. 在类对象的外部
    语法格式:类对象.属性名 或 实例对象.属性名
    类对象的所有实例对象都有一个指向类对象的指针,所以类对象的所有实例对象都可以访问类属性。
    之所以添加前缀“类对象”,是为了表明类属性被哪个类对象所绑定。
class MyClass(object):
    cal = 66
	def do_sth(self):
	    #在类对象内部(方法外)绑定属性
		cal = 66
		def do_sth(self):
		    #在类对象内部(方法中)访问类属性。  
			print(MyClass.cal)

MyClass.cal

[out]
66

mc = MyClass()
mc.cal

[out]
66

mc.do_sth()
[out]
66

#在类对象的外部绑定类属性 
MyClass.ca2 = 88
print(MyClass.ca2)

[out]
88

print(mc.ca2)

[out]
88

#在类对象的外部修改类属性 
MyClass.ca2 = 99
print(MyClass.ca2)

[out]
99

print(mc.ca2)

[out]
99
class MyClass(object):
    #在类对象内部(方法外)绑定类属性
    cal = 66
	
	def do_sth(self):
	    #在类对象内部(方法中)访问类属性
        print(MyClass.cal)
		
	def do_another(self):
	    #在类对象内部(方法中)访问类属性
        print(MyClass.ca2)

mc = MyClass()

#在类对象外部调用类方法,使得在类对象内部(方法中)访问类属性
mc.do_another()
[out]
99

访问实例属性和类属性都可以通过“实例对象.属性名”的方式。当通过“实例对象.属性名”的方式访问属性时,会先查找制定的实例对象中有没有指定名称的实例属性,如果没有,在查找对应的类对象中有没有制定名称的类属性。所以,当通过“实例对象.属性名”的方式访问属性时,如果实例属性和类属性同名,实例属性会屏蔽掉类属性。

当通过“实例对象.属性名 = 属性值”的方式绑定属性时,这里的属性指标是实例属性(因为类属性没有这样的绑定方式),所以之会查找制定的实例对象有没有绑定制定名称的实例属性,如果没有则进行绑定,如果已经绑定了,则对属性值进行修改。

class Person(object):
    age = 18
	
p = Person()

#在实例对象p中没有找到名为age的实例属性,然后在类对象Person中找到了名为age的类属性
print(p.age)

[out]
18

#打印名为age的类属性
print(Person.age)

p.age = 19

print(p.age)

[out]: 19

print(Person.age)

[out]: 18

#删除实例对象p绑定的实例属性
del p.age
print(p.age)

[out]: 18

p1 = Person()
p2 = Person()

p1.age += 2
print(Person.age)
print(p1.age)
print(p2.age)

[out]: 18
20
18

Person.age += 3
print(Person.age)
print(p1.age)
print(p2.age)

[out]: 21
20
21

转载请注明:南梦婷的博客 » 点击阅读原文


Comments

Content