面向对象

面向对象编程——Object Oriented Programming,简称OOP,是一种程序设计思想。OOP把对象作为程序的基本单元,一个对象包含了数据和操作数据的函数

类和实例

这是面向对象最重要的概念,就是将面向对象的概念具象化。
这里我们先定义一条狗,狗要有姓名和年龄。

# 我们在这里定义一个狗的类
class Dog(object):  
    # __init__ 为初始化方法
    def __init__(self, name, age):  
        self.name = name  
        self.age = age
    # 我们再写一个方法,打印狗的名字和年龄
    def print_dog(self):  
        print('%s: %s' % (self.name, self.age))

接下来我们就调用一下这个类

# 我们首先先给dog赋值,名字和年龄
dog = Dog("小花", 12) 
# 调用我们之前写的打印方法
dog.print_dog()
运行结果:
小花: 12

这样我们就简单的将狗进行了数据封装,我们只需要知道我们在创建狗的实例变量的时候需要传名字和年龄就可以了。
然后我们还可以在里面增加方法,而且我们在调用方法的时候根本不去关心内部的运行原理。

访问限制

在Class内部,可以有属性和方法,而外部代码可以调用。这样就可以很好的隐藏了内部的实现逻辑。
可是,上面的代码中,外部还是可以自由的修改实例中的属性值。
我们希望内部属性不能被外部修改的话,我们就可以在属性名称前加上两个下划线__
在Python中,实例的变量名如果以__开头,就变成了一个私有变量(private),只有内部可以访问,外部不能访问。

class Dog(object):  
    def __init__(self, name, age):  
        self.__name = name  
        self.__age = age  

    def print_dog(self):  
        print('%s: %s' % (self.__name, self.__age))

我们这边运行一下:

dog = Dog("小花", 12)  
dog.print_dog()  
print(dog.__name)
运行结果:
小花: 12
Traceback (most recent call last):
File "D:/WorkSpace/python/test.py", line 12, in <module>
print(dog.__name)
AttributeError: 'Dog' object has no attribute '__name'

不过如果我们需要对内部的值进行修改的话怎么办呢?这里我们可以新建方法,get_name和set_name。

class Dog(object):  
    def __init__(self, name, age):  
        self.__name = name  
        self.__age = age  

    def print_dog(self):  
        print('%s: %s' % (self.__name, self.__age))

    # 获取__name
    def get_name(self):
        return self.__name

    # 给__name赋值
    def set_name(self, name):
        self.__name = name

这里我们再运行一下:

dog = Dog("小花", 12)  
dog.print_dog()  
print(dog.get_name())
运行结果:
小花: 12
小花
  • 在Python中,变量名类似__xxx__的,也就是以双下划线开头,并且以双下划线结尾的,是特殊变量,特殊变量是可以直接访问的,不是private变量。
  • 以一个下划线开头的实例变量名,比如_name,这样的实例变量外部是可以访问的,但是,这样的变量意思是告诉你请不要随便访问我,我是私有变量。

继承和多态

在OOP程序设计中,当我们定义一个新class的时候,可以从已有的class继承,新的class称为子类(Subclass),而被继承的class称为基类、父类或超类(Base class、Super class)。

class People(object):
    def drink(self):
        print('People are drinking water')

class Chinese(People):
    pass

class Japanese(People):
    pass

我们这边调用运行一下:

chinese = Chinese()  
chinese.drink()  
  
japanese = Japanese()  
japanese.drink()
运行结果:
People are drinking water
People are drinking water

这里可以看出来,由于People有drink方法,他的子类Chinese和Japanese什么都没有做,就继承了drink方法。

获取对象信息

一、使用type()函数

使用type()函数,可以获取任何数据的类型。如果要判断一个数据是不是函数,可以使用types模块中定义的常量,如:types.FunctionType、types.LambdaType。

二、使用isinstance()函数

isinstance函数判断的是一个对象是否是该类型或位于该类型的父类继承链上。isinstance还可以判断一个变量是否是某些类型的一种,用元组写多种类型。

三、使用dir()函数

1.如果要获得一个对象全部的属性和方法,可以使用dir()函数。它返回一个包含 字符串的list。

2.类似“__xxx__”的属性和方法在Python中都是有特殊用途的,比如len()函数获取对象的长度。但实际上,在len函数内部它会去自动调用对象的__len__()方法,所以,你可以在类中自己设定一个__len__()方法,让len返回你想要返回的长度。

四、操作一个对象状态

如getattr() 获取、setattr() 设置 和hasattr() 有没有 方法,可以直接操作一个对象的状态。

hasattr(obj,'x') #有属性‘x’吗?
setattr(obj,'y',18) #设置一个属性‘y’,值为18.
getattr(obj,'y') #获取属性y
getattr(obj,'z',404) #获取属性z,如果不存在,就返回默认值404.

实例属性和类属性

实例属性属于各个实例所有,互不干扰;
类属性属于类所有,所有实例共享一个属性;
不要对实例属性和类属性使用相同的名字,否则将产生难以发现的错误。


周兆东
107 声望21 粉丝

一个java小白的成长之路。。。