图解Python 【第五篇】:面向对象-类-初级基础篇

时间:2023-03-08 15:50:03

由于类的内容比较多,分为类-初级基础篇类-进阶篇

类的内容总览图:

图解Python 【第五篇】:面向对象-类-初级基础篇


本节主要讲基础和面向对象的特性

本节内容一览图:
图解Python 【第五篇】:面向对象-类-初级基础篇


前言总结介绍:

面向对象是一种编程方式,此编程方式的实现是基于对 对象 的使用

  • 类 是一个模板,模板中包装了多个“函数”供使用(可以讲多函数中公用的变量封装到对象中)
  • 对象,根据模板创建的实例(即:对象),实例用于调用被包装在类中的函数,对象是一个类的实例
  • 实例(instance):一个对象的实例化实现。
  • 标识(identity):每个对象的实例都需要一个可以唯一标识这个实例的标记。
  • 实例属性(instance attribute):一个对象就是一组属性的集合。
  • 实例方法(instance method):所有存取或者更新对象某个实例一条或者多条属性的函数的集合
  • 类属性(classattribute):属于一个类中所有对象的属性,不会只在某个实例上发生变化
  • 类方法(classmethod):那些无须特定的对性实例就能够工作的从属于类的函数。
  • 面向对象三大特性:封装、继承和多态

关于编程方式请点击这里


图解Python 【第五篇】:面向对象-类-初级基础篇一、基础

面向对象编程是一种编程方式,此编程方式的落地需要使用 “类” 和 “对象” 来实现,所以,面向对象编程其实就是对 “类” 和 “对象” 的使用。

  类就是一个模板,模板里可以包含多个函数,函数里实现一些功能

  对象则是根据模板创建的实例,通过实例对象可以执行类中的函数

图解Python 【第五篇】:面向对象-类-初级基础篇

  • class是关键字,表示类
  • 创建对象,类名称后加括号即可

类中的函数第一个参数必须是self(详细见:类的三大特性之封装)
   类中定义的函数叫做 “方法”


先上图说说类的各种写法以及意思(可以略过)

图解Python 【第五篇】:面向对象-类-初级基础篇


一、类的成员

类的成员分为三类:字段、方法和属性

图解Python 【第五篇】:面向对象-类-初级基础篇

注:所有成员中,只有普通字段的内容保存对象中,即:根据此类创建了多少对象,在内存中就有多少个普通字段。而其他的成员,则都是保存在类中,即:无论对象的多少,在内存中只创建一份。

1、字段

字段:区分普通字段和静态字段,在定义和使用中有所区别,最本质的区别是内存中保存的位置不同

  • 普通字段属于对象
  • 静态字段属于类
class Province:

    # 静态字段
country = '中国' def __init__(self, name): # 普通字段
self.name = name # 直接访问普通字段
obj = Province('河北省')
print obj.name # 直接访问静态字段
Province.country

字段的定义和使用(普通字段及静态字段)

注意:特殊方法“init”前后有两个下划线!!!

注意到__init__方法的第一个参数永远是self,表示创建的实例本身,因此,在__init__方法内部,就可以把各种属性绑定到self,因为self就指向创建的实例本身。

有了__init__方法,在创建实例的时候,就不能传入空的参数了,必须传入与__init__方法匹配的参数,但self不需要传,Python解释器自己会把实例变量传进去:

区别:

和普通的函数相比,在类中定义的函数只有一点不同,就是第一个参数永远是实例变量self,并且,调用时,不用传递该参数。除此之外,类的方法和普通函数没有什么区别,所以,你仍然可以用默认参数、可变参数、关键字参数和命名关键字参数

由上述代码可以看出普通字段需要通过对象来访问 静态字段通过类访问,在使用上可以看出普通字段和静态字段的归属是不同的。其内容在内存中的存储方式类似于下图:

图解Python 【第五篇】:面向对象-类-初级基础篇

由上图可见:

  • 静态字段在内存中只保存一份
  • 普通字段在每个对象中都要保存一份

应用场景:通过类创建对象时,如果每个对象都具有相同的字段,那么就使用静态字段

字段补充内容:

图解Python 【第五篇】:面向对象-类-初级基础篇
class Province:
country = "中国" def __init__(self, name):
self.name = name def show(self):
print(self.name) country:已经在内存存储完成
name:还没有对象进行实例化,在内存中还没有存储
图解Python 【第五篇】:面向对象-类-初级基础篇

2、方法

图解Python 【第五篇】:面向对象-类-初级基础篇

方法包括:普通方法、静态方法和类方法,三种方法在内存中都归属于类,区别在于调用的方式不同。

  • 普通方法:由对象调用;至少一个self参数;执行普通方法时,自动将调用该方法的对象赋值给self
  • 类方法:由调用; 至少一个cls参数,另外添加了一个@classmethod的关键字;执行类方法时,自动将调用该方法的复制给cls
  • 静态方法:由调用;无默认参数,另外添加了一个@staticmethod的关键字;
class Foo:

    def __init__(self, name):
self.name = name def ord_func(self):
""" 定义普通方法,至少有一个self参数 """ # print self.name
print '普通方法' @classmethod
def class_func(cls):
""" 定义类方法,至少有一个cls参数 """ print '类方法' @staticmethod
def static_func():
""" 定义静态方法 ,无默认参数""" print '静态方法' # 调用普通方法
f = Foo()
f.ord_func() # 调用类方法
Foo.class_func() # 调用静态方法
Foo.static_func()

方法的定义及调用(普通方法,静态方法及类方法)

图解Python 【第五篇】:面向对象-类-初级基础篇

相同点:对于所有的方法而言,均属于,在内存中也只保存一份

不同点:方法的调用者不同,调用方法时自动传入的参数不同

3、属性

了解了Python类中的方法,属性就相对容易理解了,因为Python中的属性其实就是普通方法的变种。

对于属性要学习的知识点:

  • 属性的基本使用
  • 属性的定义方式(2种)

 3.1 属性的基本使用

# ############### 定义 ###############
class Foo: def func(self):
pass # 定义属性
@property
def prop(self):
pass
# ############### 调用 ###############
foo_obj = Foo() foo_obj.func()
foo_obj.prop #调用属性

属性的定义及调用

图解Python 【第五篇】:面向对象-类-初级基础篇

由属性的定义和调用要注意一下几点:

  • 定义时,在普通方法的基础上添加 @property 装饰器;
  • 定义时,属性仅有一个self参数
  • 调用时,无需括号
               方法:foo_obj.func()
               属性:foo_obj.prop

注意:属性存在意义是:访问属性时可以制造出和访问字段完全相同的假象

属性由方法变种而来,如果Python中没有属性,方法完全可以代替其功能。

实例:对于主机列表页面,每次请求不可能把数据库中的所有内容都显示到页面上,而是通过分页的功能局部显示,所以在向数据库中请求数据时就要显示的指定获取从第m条到第n条的所有数据(即:limit m,n),这个分页的功能包括:

  • 根据用户请求的当前页和总数据条数计算出 m 和 n
  • 根据m 和 n 去数据库中请求数据
# ############### 定义 ###############
class Pager: def __init__(self, current_page):
# 用户当前请求的页码(第一页、第二页...)
self.current_page = current_page
# 每页默认显示10条数据
self.per_items = 10 @property
def start(self):
val = (self.current_page - 1) * self.per_items
return val @property
def end(self):
val = self.current_page * self.per_items
return val # ############### 调用 ############### p = Pager(1)
p.start 就是起始值,即:m
p.end 就是结束值,即:n

代码实现

从上述可见,Python的属性的功能是:属性内部进行一系列的逻辑计算,最终将计算结果返回。

2、属性的定义方式(2种)

属性的定义方式:

  • 装饰器:在方法上应用装饰器
  • 静态字段:在类中定义值为property对象的静态字段

装饰器方式:在类的普通方法上应用@property装饰器

我们知道Python中的类有经典类和新式类,新式类的属性比经典类的属性丰富。( 如果类继object,那么该类是新式类 )

补充:经典类和新式类

图解Python 【第五篇】:面向对象-类-初级基础篇
经典类,具有一种@property装饰器(如上一步实例)

# ############### 定义 ###############
class Goods: @property
def price(self):
return "wupeiqi"
# ############### 调用 ###############
obj = Goods()
result = obj.price # 自动执行 @property 修饰的 price 方法,并获取方法的返回值

经典类案例

新式类,具有三种@property装饰器

# ############### 定义 ###############
class Goods(object): @property
def price(self):
print '@property' @price.setter
def price(self, value):
print '@price.setter' @price.deleter
def price(self):
print '@price.deleter' # ############### 调用 ###############
obj = Goods() obj.price # 自动执行 @property 修饰的 price 方法,并获取方法的返回值 obj.price = 123 # 自动执行 @price.setter 修饰的 price 方法,并将 123 赋值给方法的参数 del obj.price # 自动执行 @price.deleter 修饰的 price 方法

新式类案例

注:经典类中的属性只有一种访问方式,其对应被 @property 修饰的方法
      新式类中的属性有三种访问方式,并分别对应了三个被@property、@方法名.setter、@方法名.deleter修饰的方法

由于新式类中具有三种访问方式,我们可以根据他们几个属性的访问特点,分别将三个方法定义为对同一个属性:获取、修改、删除

class Goods(object):

    def __init__(self):
# 原价
self.original_price = 100
# 折扣
self.discount = 0.8 @property
def price(self):
# 实际价格 = 原价 * 折扣
new_price = self.original_price * self.discount
return new_price @price.setter
def price(self, value):
self.original_price = value @price.deltter
def price(self, value):
del self.original_price obj = Goods()
obj.price # 获取商品价格
obj.price = 200 # 修改商品原价
del obj.price # 删除商品原价 实例

案例

静态字段方式,创建值为property对象的静态字段

当使用静态字段的方式创建属性时,经典类和新式类无区别

class Foo:

    def get_bar(self):
return 'wupeiqi' BAR = property(get_bar) obj = Foo()
reuslt = obj.BAR # 自动调用get_bar方法,并获取方法的返回值
print reuslt

案例

property的构造方法中有个四个参数

  • 第一个参数是方法名,调用 对象.属性 时自动触发执行方法
  • 第二个参数是方法名,调用 对象.属性 = XXX 时自动触发执行方法
  • 第三个参数是方法名,调用 del 对象.属性 时自动触发执行方法
  • 第四个参数是字符串,调用 对象.属性.__doc__ ,此参数是该属性的描述信息
class Foo:

    def get_bar(self):
return 'wupeiqi' # *必须两个参数
def set_bar(self, value):
return return 'set value' + value def del_bar(self):
return 'wupeiqi' BAR = property(get_bar, set_bar, del_bar, 'description...') obj = Foo() obj.BAR # 自动调用第一个参数中定义的方法:get_bar
obj.BAR = "alex" # 自动调用第二个参数中定义的方法:set_bar方法,并将“alex”当作参数传入
del Foo.BAR # 自动调用第三个参数中定义的方法:del_bar方法
obj.BAE.__doc__ # 自动获取第四个参数中设置的值:description...

案例

由于静态字段方式创建属性具有三种访问方式,我们可以根据他们几个属性的访问特点,分别将三个方法定义为对同一个属性:获取、修改、删除

class Goods(object):

    def __init__(self):
# 原价
self.original_price = 100
# 折扣
self.discount = 0.8 def get_price(self):
# 实际价格 = 原价 * 折扣
new_price = self.original_price * self.discount
return new_price def set_price(self, value):
self.original_price = value def del_price(self, value):
del self.original_price PRICE = property(get_price, set_price, del_price, '价格属性描述...') obj = Goods()
obj.PRICE # 获取商品价格
obj.PRICE = 200 # 修改商品原价
del obj.PRICE # 删除商品原价

案例

注意:Python WEB框架 Django 的视图中 request.POST 就是使用的静态字段的方式创建的属性

class WSGIRequest(http.HttpRequest):
def __init__(self, environ):
script_name = get_script_name(environ)
path_info = get_path_info(environ)
if not path_info:
# Sometimes PATH_INFO exists, but is empty (e.g. accessing
# the SCRIPT_NAME URL without a trailing slash). We really need to
# operate as if they'd requested '/'. Not amazingly nice to force
# the path like this, but should be harmless.
path_info = '/'
self.environ = environ
self.path_info = path_info
self.path = '%s/%s' % (script_name.rstrip('/'), path_info.lstrip('/'))
self.META = environ
self.META['PATH_INFO'] = path_info
self.META['SCRIPT_NAME'] = script_name
self.method = environ['REQUEST_METHOD'].upper()
_, content_params = cgi.parse_header(environ.get('CONTENT_TYPE', ''))
if 'charset' in content_params:
try:
codecs.lookup(content_params['charset'])
except LookupError:
pass
else:
self.encoding = content_params['charset']
self._post_parse_error = False
try:
content_length = int(environ.get('CONTENT_LENGTH'))
except (ValueError, TypeError):
content_length = 0
self._stream = LimitedStream(self.environ['wsgi.input'], content_length)
self._read_started = False
self.resolver_match = None def _get_scheme(self):
return self.environ.get('wsgi.url_scheme') def _get_request(self):
warnings.warn('`request.REQUEST` is deprecated, use `request.GET` or '
'`request.POST` instead.', RemovedInDjango19Warning, 2)
if not hasattr(self, '_request'):
self._request = datastructures.MergeDict(self.POST, self.GET)
return self._request @cached_property
def GET(self):
# The WSGI spec says 'QUERY_STRING' may be absent.
raw_query_string = get_bytes_from_wsgi(self.environ, 'QUERY_STRING', '')
return http.QueryDict(raw_query_string, encoding=self._encoding) # ############### 看这里看这里 ###############
def _get_post(self):
if not hasattr(self, '_post'):
self._load_post_and_files()
return self._post # ############### 看这里看这里 ###############
def _set_post(self, post):
self._post = post @cached_property
def COOKIES(self):
raw_cookie = get_str_from_wsgi(self.environ, 'HTTP_COOKIE', '')
return http.parse_cookie(raw_cookie) def _get_files(self):
if not hasattr(self, '_files'):
self._load_post_and_files()
return self._files # ############### 看这里看这里 ###############
POST = property(_get_post, _set_post) FILES = property(_get_files)
REQUEST = property(_get_request) Django源码

实际应用案例

所以,定义属性共有两种方式,分别是【装饰器】和【静态字段】,而【装饰器】方式针对经典类和新式类又有所不同。

其他案例:

class Pager:
def __init__(self, all_count):
self.all_count = all_count @property # 定义属性
def all_pager(self):
a1, a2 = divmod(self.all_count, 10)
if a2 == 0:
return a1
else:
return a1 + 1 @all_pager.setter # 给方法添加字段的赋值功能
def all_pager(self, value):
print(value) @all_pager.deleter # 给方法添加字段的删除功能
def all_pager(self):
print("del all_pager") p = Pager(101)
# 不定义属性
# p.all_count # 调用字段
# result = p.all_pager() # 调用方法
# print(result) # 定义属性
ret = p.all_pager # 使用调用字段的形式 调用方法
print(ret) p.all_pager = 200
print(p.all_pager) # 使用调用字段的形式 调用方法 del p.all_pager

应用装饰器定义方式

class Pager:
def __init__(self, all_count):
self.all_count = all_count def f1(self):
return 123 def f2(self, value):
return value def f3(self):
return "f3" foo = property(fget=f1, fset=f2, fdel=f3) p = Pager(101) result = p.foo
print(result, "1") p.foo = "alex"
result = p.foo
print(result, "2") del p.foo

静态字段定义方式


图解Python 【第五篇】:面向对象-类-初级基础篇二、面向对象三大特性

面向对象的三大特性是指:封装继承多态

一、封装

封装,顾名思义就是将内容封装到某个地方,以后再去调用被封装在某处的内容。

所以,在使用面向对象的封装特性时,需要:

  • 将内容封装到某处
  • 从某处调用被封装的内容

第一步:将内容封装到某处

图解Python 【第五篇】:面向对象-类-初级基础篇

self 是一个形式参数,当执行 obj1 = Foo('wupeiqi', 18 ) 时,self 等于 obj1

当执行 obj2 = Foo('alex', 78 ) 时,self 等于 obj2

所以,内容其实被封装到了对象 obj1 和 obj2 中,每个对象中都有 name 和 age 属性,在内存里类似于下图来保存。

图解Python 【第五篇】:面向对象-类-初级基础篇

第二步:从某处调用被封装的内容

调用被封装的内容时,有两种情况:

  • 通过对象直接调用
  • 通过self间接调用

1、通过对象直接调用被封装的内容

上图展示了对象 obj1 和 obj2 在内存中保存的方式,根据保存格式可以如此调用被封装的内容:对象.属性名

class Foo:
 
    def __init__(self, name, age):
        self.name = name
        self.age = age
 
obj1 = Foo('wupeiqi', 18)
print obj1.name    # 直接调用obj1对象的name属性
print obj1.age     # 直接调用obj1对象的age属性
 
obj2 = Foo('alex', 73)
print obj2.name    # 直接调用obj2对象的name属性
print obj2.age     # 直接调用obj2对象的age属性

2、通过self间接调用被封装的内容

执行类中的方法时,需要通过self间接调用被封装的内容

class Foo:
  
    def __init__(self, name, age):
        self.name = name
        self.age = age
  
    def detail(self):
        print self.name
        print self.age
  
obj1 = Foo('wupeiqi', 18)
obj1.detail()  # Python默认会将obj1传给self参数,即:obj1.detail(obj1),所以,此时方法内部的 self = obj1,即:self.name 是 wupeiqi ;self.age 是 18
  
obj2 = Foo('alex', 73)
obj2.detail()  # Python默认会将obj2传给self参数,即:obj1.detail(obj2),所以,此时方法内部的 self = obj2,即:self.name 是 alex ; self.age 是 78

综上所述,对于面向对象的封装来说,其实就是使用构造方法将内容封装到 对象 中,然后通过对象直接或者self间接获取被封装的内容。


二、继承

继承,面向对象中的继承和现实生活中的继承相同,即:子可以继承父的内容。

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

图解Python 【第五篇】:面向对象-类-初级基础篇

例如:

  猫可以:喵喵叫、吃、喝、拉、撒

  狗可以:汪汪叫、吃、喝、拉、撒

如果我们要分别为猫和狗创建一个类,那么就需要为 猫 和 狗 实现他们所有的功能,如下所示:

class 猫:

    def 喵喵叫(self):
print '喵喵叫' def 吃(self):
# do something def 喝(self):
# do something def 拉(self):
# do something def 撒(self):
# do something class 狗: def 汪汪叫(self):
print '喵喵叫' def 吃(self):
# do something def 喝(self):
# do something def 拉(self):
# do something def 撒(self):
# do something

伪代码

上述代码不难看出,吃、喝、拉、撒是猫和狗都具有的功能,而我们却分别的猫和狗的类中编写了两次。如果使用 继承 的思想,如下实现:

  动物:吃、喝、拉、撒

     猫:喵喵叫(猫继承动物的功能)

     狗:汪汪叫(狗继承动物的功能)

class 动物:

    def 吃(self):
# do something def 喝(self):
# do something def 拉(self):
# do something def 撒(self):
# do something # 在类后面括号中写入另外一个类名,表示当前类继承另外一个类
class 猫(动物): def 喵喵叫(self):
print '喵喵叫' # 在类后面括号中写入另外一个类名,表示当前类继承另外一个类
class 狗(动物): def 汪汪叫(self):
print '喵喵叫'

伪代码

class Animal:

    def eat(self):
print "%s 吃 " %self.name def drink(self):
print "%s 喝 " %self.name def shit(self):
print "%s 拉 " %self.name def pee(self):
print "%s 撒 " %self.name class Cat(Animal): def __init__(self, name):
self.name = name
self.breed = '猫' def cry(self):
print '喵喵叫' class Dog(Animal): def __init__(self, name):
self.name = name
self.breed = '狗' def cry(self):
print '汪汪叫' # ######### 执行 ######### c1 = Cat('小白家的小黑猫')
c1.eat() c2 = Cat('小黑的小白猫')
c2.drink() d1 = Dog('胖子家的小瘦狗')
d1.eat()

代码实例

所以,对于面向对象的继承来说,其实就是将多个类共有的方法提取到父类中,子类仅需继承父类而不必一一实现每个方法。

super(Student, self).__init__(name, gender) 去初始化父类

需要 调用父类的 super(子类,子类实例)的 __init__ 方法

         继承一个类super(该类名,self).__init__(继承的属性)
初始化父类

小结

继承可以把父类的所有功能都直接拿过来,这样就不必重零做起,子类只需要新增自己特有的方法,也可以把父类不适合的方法覆盖重写

函数isinstance()可以判断一个变量的类型,既可以用在Python内置的数据类型如str、list、dict,也可以用在我们自定义的类,它们本质上都是数据类型。

:除了子类和父类的称谓,你可能看到过 派生类 和 基类 ,他们与子类和父类只是叫法不同而已。

图解Python 【第五篇】:面向对象-类-初级基础篇

学习了继承的写法之后,我们用代码来是上述阿猫阿狗的功能:

class Animal:

    def eat(self):
print "%s 吃 " %self.name def drink(self):
print "%s 喝 " %self.name def shit(self):
print "%s 拉 " %self.name def pee(self):
print "%s 撒 " %self.name class Cat(Animal): def __init__(self, name):
self.name = name
self.breed = '猫' def cry(self):
print '喵喵叫' class Dog(Animal): def __init__(self, name):
self.name = name
self.breed = '狗' def cry(self):
print '汪汪叫' # ######### 执行 ######### c1 = Cat('小白家的小黑猫')
c1.eat() c2 = Cat('小黑的小白猫')
c2.drink() d1 = Dog('胖子家的小瘦狗')
d1.eat()

代码实例

那么问题又来了,多继承呢?

  • 是否可以继承多个类
  • 如果继承的多个类每个类中都定了相同的函数,那么那一个会被使用呢?

1、Python的类可以继承多个类,Java和C#中则只能继承一个类

2、Python的类如果继承了多个类,那么其寻找方法的方式有两种,分别是:深度优先广度优先

图解Python 【第五篇】:面向对象-类-初级基础篇

  • 当类是经典类时,多继承情况下,会按照深度优先方式查找
  • 当类是新式类时,多继承情况下,会按照广度优先方式查找

经典类和新式类,从字面上可以看出一个老一个新,新的必然包含了跟多的功能,也是之后推荐的写法,从写法上区分的话,如果 当前类或者父类继承了object类,那么该类便是新式类,否则便是经典类。

新式类和经典类声明的最大不同在于,所有新式类必须继承至少一个父类。如果没有可继承的类,则可继承 object 类。object 是“所有类之母” ,它位于所有类继承结构的最上层。如果没有直接或间接的子类化一个对象,那么就定义了一个经典类。即如果没有指定一个父类,或者如果所子类化的基本类没有父类,这样就是创建了一个经典类。

在 Python3 中定义的类,默认就是新式类,而在 Python2 中要定义一个新式类则必须继承 object 或者继承一个新式类。

图解Python 【第五篇】:面向对象-类-初级基础篇 图解Python 【第五篇】:面向对象-类-初级基础篇

class D:

    def bar(self):
print 'D.bar' class C(D): def bar(self):
print 'C.bar' class B(D): def bar(self):
print 'B.bar' class A(B, C): def bar(self):
print 'A.bar' a = A()
# 执行bar方法时
# 首先去A类中查找,如果A类中没有,则继续去B类中找,如果B类中么有,则继续去D类中找,如果D类中么有,则继续去C类中找,如果还是未找到,则报错
# 所以,查找顺序:A --> B --> D --> C
# 在上述查找bar方法的过程中,一旦找到,则寻找过程立即中断,便不会再继续找了
a.bar()

经典类多继承

class D(object):

    def bar(self):
print 'D.bar' class C(D): def bar(self):
print 'C.bar' class B(D): def bar(self):
print 'B.bar' class A(B, C): def bar(self):
print 'A.bar' a = A()
# 执行bar方法时
# 首先去A类中查找,如果A类中没有,则继续去B类中找,如果B类中么有,则继续去C类中找,如果C类中么有,则继续去D类中找,如果还是未找到,则报错
# 所以,查找顺序:A --> B --> C --> D
# 在上述查找bar方法的过程中,一旦找到,则寻找过程立即中断,便不会再继续找了
a.bar()

新式类多继承

经典类:首先去A类中查找,如果A类中没有,则继续去B类中找,如果B类中么有,则继续去D类中找,如果D类中么有,则继续去C类中找,如果还是未找到,则报错

新式类:首先去A类中查找,如果A类中没有,则继续去B类中找,如果B类中么有,则继续去C类中找,如果C类中么有,则继续去D类中找,如果还是未找到,则报错

多重继承的目的是从两种继承树中分别选择并继承出子类,以便组合功能使用

重载方法

可以随时重载父类的方法。 重载父方法的一个原因是:您可能希望在子类中使用特殊或不同的方法功能

基本重载方法

下表列出了可以在自己的类中覆盖的一些通用方法 -

编号 方法 描述 调用示例
1 __init__ ( self [,args...] ) 构造函数(带任意可选参数) obj = className(args)
2 __del__( self ) 析构函数,删除一个对象 del obj
3 __repr__( self ) 可评估求值的字符串表示 repr(obj)
4 __str__( self ) 可打印的字符串表示 str(obj)
5 __cmp__ ( self, x ) 对象比较 cmp(obj, x)

三、多态 

Pyhon不支持Java和C#这一类强类型语言中多态的写法,但是原生多态,其Python崇尚“鸭子类型”。

class F1:
pass class S1(F1): def show(self):
print 'S1.show' class S2(F1): def show(self):
print 'S2.show' # 由于在Java或C#中定义函数参数时,必须指定参数的类型
# 为了让Func函数既可以执行S1对象的show方法,又可以执行S2对象的show方法,所以,定义了一个S1和S2类的父类
# 而实际传入的参数是:S1对象和S2对象 def Func(F1 obj):
"""Func函数需要接收一个F1类型或者F1子类的类型""" print obj.show() s1_obj = S1()
Func(s1_obj) # 在Func函数中传入S1类的对象 s1_obj,执行 S1 的show方法,结果:S1.show s2_obj = S2()
Func(s2_obj) # 在Func函数中传入Ss类的对象 ss_obj,执行 Ss 的show方法,结果:S2.show

Python伪代码实现Java或C#的多态

class F1:
pass class S1(F1): def show(self):
print 'S1.show' class S2(F1): def show(self):
print 'S2.show' def Func(obj):
print obj.show() s1_obj = S1()
Func(s1_obj) s2_obj = S2()
Func(s2_obj)

Python “鸭子类型”

动态语言的“鸭子类型”,它并不要求严格的继承体系,一个对象只要“看起来像鸭子,走起路来像鸭子”,那它就可以被看做是鸭子


总结 

访问限制:

如果要让内部属性不被外部访问,可以把属性的名称前加上两个下划线__,在Python中,实例的变量名如果以__开头,就变成了一个私有变量(private),只有内部可以访问,外部不能访问

以上就是本节对于面向对象初级知识的介绍,总结如下:

用例子来说明:

图解Python 【第五篇】:面向对象-类-初级基础篇

4.@classmethod修饰器
调用的时候用类名,而不是某个对象
5.@property修饰器修饰方法
像访问属性一样调用方法


声明:

本人在学习老男孩python自动化网络课程后,结合所学整理做次笔记,本文内容多出

Alex老师博客:http://www.cnblogs.com/alex3714/articles/5740985.html

武沛齐老师博客:http://www.cnblogs.com/wupeiqi/articles/5453708.html

感谢老男孩教育老师Alex,武沛齐老师,本文多从二位老师文章中结合整理

http://www.cnblogs.com/wupeiqi/p/4766801.html

http://www.yiibai.com/python/python_classes_objects.html