欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

Python学习之面向对象编程

程序员文章站 2022-06-22 17:30:39
面向对象编程——Object Oriented Programming,简称OOP,是一种程序设计思想。OOP把对象作为程序的基本单元,一个对象包含了数据和操作数据的函数。 类和实例 定义 上面代码中: class后面紧接的是类名,类名以大写字母开头 (object)是该类从哪个类继承下来的 使用时 ......

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

Python学习之面向对象编程

类和实例

定义

class Student(object):
    pass

stone = Student()
stone.name = "stone"
stone.age = 2

print(stone.name, stone.age)

 

上面代码中:

  • class后面紧接的是类名,类名以大写字母开头
  • (object)是该类从哪个类继承下来的
  • 使用时候可以*的给实例变量绑定属性

方法

class Student(object):
    def __init__(self, name, age):
        self.name = name
        self.age = age

    def print_info(self):
        print(self.name, self.age)
        
stone = Student("stone", 18)
stone.print_info()

 

上面代码中:

  • __init__ 方法的第一个参数永远是 self ,表示创建的实例本身,因此,在 __init__ 方法内部,就可以把各种属性绑定到 self ,因为 self 就指向创建的实例本身。类似于java的构造函数。
  • 定义一个方法,除了第一个参数是 self 外,其他和普通函数一样。要调用一个方法,只需要在实例变量上直接调用,除了 self 不用传递,其他参数正常传入。

访问限制

__
__xxx__

 

继承和多态

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

静态语言 vs 动态语言:

对于静态语言(例如Java)来说,如果需要传入 Animal 类型,则传入的对象必须是 Animal类型或者它的子类,否则,将无法调用 Animal 中的方法。对于Python这样的动态语言来说,则不一定需要传入 Animal 类型。我们只需要保证传入的对象有 Animal 中的方法就可以了。

对象信息

使用type()

>>> import types
>>> def fn():
...     pass
...
>>> type(fn)==types.FunctionType
True
>>> type(abs)==types.BuiltinFunctionType
True
>>> type(lambda x: x)==types.LambdaType
True
>>> type((x for x in range(10)))==types.GeneratorType
True

 

以上代码可以看出,判断基本数据类型可以直接写 int , str 等,但如果要判断一个对象是否是函数怎么办?可以使用 types 模块中定义的常量。

使用isinstance()

>>> isinstance([1, 2, 3], (list, tuple))
True
>>> isinstance((1, 2, 3), (list, tuple))
Tru

 

可以判断一个变量是否是某些类型中的一种,比如上面的代码就可以判断是否是list或者tuple

使用dir()

如果要获得一个对象的所有属性和方法,可以使用 dir() 函数,它返回一个包含字符串的list,比如,获得一个str对象的所有属性和方法:

>>> dir('ABC')
['__add__', '__class__',..., '__subclasshook__', 'capitalize', 'casefold',..., 'zfill']

 

类似 __xxx__ 的属性和方法在Python中都是有特殊用途的,比如 __len__ 方法返回长度。在Python中,如果你调用 len() 函数试图获取一个对象的长度,实际上,在 len() 函数内部,它自动去调用该对象的 __len__() 方法,所以,下面的代码是等价的:

>>> len('ABC')
3
>>> 'ABC'.__len__()
3

 

我们自己写的类,如果也想用 len(myObj) 的话,就自己写一个 __len__() 方法:

>>> class MyDog(object):
...     def __len__(self):
...         return 100
...
>>> dog = MyDog()
>>> len(dog)
100

 

仅仅把属性和方法列出来是不够的,配合 getattr() 、 setattr() 以及 hasattr() ,我们可以直接操作一个对象的状态:

>>> class MyObject(object):
...     def __init__(self):
...         self.x = 9
...     def power(self):
...         return self.x * self.x
...
>>> obj = MyObject()

 

紧接着,可以测试该对象的属性:

>>> hasattr(obj, 'x') # 有属性'x'吗?
True
>>> obj.x
9
>>> hasattr(obj, 'y') # 有属性'y'吗?
False
>>> setattr(obj, 'y', 19) # 设置一个属性'y'
>>> hasattr(obj, 'y') # 有属性'y'吗?
True
>>> getattr(obj, 'y') # 获取属性'y'
19
>>> obj.y # 获取属性'y'
19

 

也可以获得对象的方法:

>>> hasattr(obj, 'power') # 有属性'power'吗?
True
>>> getattr(obj, 'power') # 获取属性'power'
<bound method MyObject.power of <__main__.MyObject object at 0x10077a6a0>>
>>> fn = getattr(obj, 'power') # 获取属性'power'并赋值到变量fn
>>> fn # fn指向obj.power
<bound method MyObject.power of <__main__.MyObject object at 0x10077a6a0>>
>>> fn() # 调用fn()与调用obj.power()是一样的
81

 

实例属性和类属性

类本身需要绑定一个属性:

class Student(object):
    name = 'Student'

 

当我们定义了一个类属性后,这个属性虽然归类所有,但类的所有实例都可以访问到。来测试一下:

>>> class Student(object):
...     name = 'Student'
...
>>> s = Student() # 创建实例s
>>> print(s.name) # 打印name属性,因为实例并没有name属性,所以会继续查找class的name属性
Student
>>> print(Student.name) # 打印类的name属性
Student
>>> s.name = 'Michael' # 给实例绑定name属性
>>> print(s.name) # 由于实例属性优先级比类属性高,因此,它会屏蔽掉类的name属性
Michael
>>> print(Student.name) # 但是类属性并未消失,用Student.name仍然可以访问
Student
>>> del s.name # 如果删除实例的name属性
>>> print(s.name) # 再次调用s.name,由于实例的name属性没有找到,类的name属性就显示出来了
Student

python学习交流群:125240963