Python面向对象(基础整理)

来源:互联网 发布:黑人 知乎 编辑:程序博客网 时间:2024/06/01 08:31

本文是Python复习笔记,参考文中两个链接

函数式编程的应用场景 –> 各个函数之间是独立且无共用的数据。

http://python.jobbole.com/88214/?utm_source=blog.jobbole.com&utm_medium=relatedPosts

类的创建与对象初始化
关于类与对象操作的BIFs

type() 返回对象类型
id(),查看对象id
dir(),查看对象下变量及函数
issubclass(),isinstance(), super(),类,实例,调父类
hasattr(),getattr(),setattr(),delattr()类属性操作
globals(),locals(),全局与局部的名称空间
import(),reload(),模块的导入与重载

创建类
class关键字,指定继承

定义类的成员
(1)数据成员:类变量,实例变量
(2)方法成员:类方法,实例方法

调用被封装的内容时,有两种情况:通过对象直接调用,通过self间接调用

1、通过对象直接调用被封装的内容
上图展示了对象 obj1 和 obj2 在内存中保存的方式,根据保存格式可以如此调用被封装的内容:对象.属性名
2、通过self间接调用被封装的内容
执行类中的方法时,需要通过self间接调用被封装的内容 self.属性名

使用构造方法将内容封装到对象中,然后通过对象直接或者self间接获取被封装的内容。

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

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

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    def cry(self):        print('喵喵叫')class Dog(Animal):    def __init__(self, name):        self.name = name                def cry(self):        print('汪汪叫') c1 = Cat('小白家的小黑猫')c1.eat() c2 = Cat('小黑的小白猫')c2.drink() d1 = Dog('胖子家的小瘦狗')d1.eat()

Python的类可以继承多个类,Java和C#中则只能继承一个类
Python的类如果继承了多个类,那么其寻找方法的方式有两种,分别是:深度优先和广度优先

如果 当前类或者父类继承了object类,那么该类便是新式类,否则便是经典类。
class N1(object):
class N2(N1)
当类是经典类时,多继承情况下,会按照深度优先方式查找
当类是新式类时,多继承情况下,会按照广度优先方式查找

多态:同一父类的不同子类对同一属性或方法的不同实现重新定义

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


http://python.jobbole.com/88230/

数据成员

普通字段属于对象,静态字段属于类

静态字段在内存中只保存一份,通过类访问
普通字段在每个对象中都要保存一份,通过对象访问

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

方法成员

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

普通方法:由对象调用;至少一个self参数;执行普通方法时,自动将调用该方法的对象赋值给self
类方法@classmethod:由类调用; 至少一个cls参数;执行类方法时,自动将调用该方法的类复制给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('Tom')f.ord_func() # 调用类方法Foo.class_func() # 调用静态方法Foo.static_func()

Python中的属性其实是普通方法的变种。

由属性的定义和调用要注意一下几点:
定义时,在普通方法的基础上添加 @property 装饰器
定义时,属性仅有一个self参数
调用时,无需括号

方法:foo_obj.func()
属性:foo_obj.prop

属性的定义有两种方式:
装饰器 即:在方法上应用装饰器
静态字段 即:在类中定义值为property对象的静态字段

class Goods:     @property    def price(self):        return "Yu"obj = Goods()obj.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        print(value)    @price.deleter    def price(self):        del self.original_priceobj = Goods()obj.price         # 获取商品价格80obj.price = 200   # 修改商品原价value=200del obj.price     # 删除商品原价


class Foo:    def get_bar(self):        return 'Yu'    BAR = property(get_bar)   #静态字段定义属性obj = Foo()reuslt = obj.BAR        # 自动调用get_bar方法,并获取方法的返回值print(reuslt)obj.BAR.__doc__   #调用 对象.属性.__doc__ ,此参数是该属性的描述信息

类成员的访问修饰符

对于每一个类的成员而言都有两种形式:公有成员,在任何地方都能访问;私有成员,只有在类的内部才能方法
私有成员和公有成员的定义不同:私有成员命名时,前两个字符是下划线。(特殊成员除外,例如:init\dict等)

静态字段
公有静态字段:类可以访问;类内部可以访问;派生类中可以访问
私有静态字段:仅类内部可以访问

class C:    __name = "公有静态字段"    def func(self):        print(C.__name)class D(C):    def show(self):        print(C.__name)C.__name       # 类访问            ==> 错误 obj = C()obj.func()     # 类内部可以访问     ==> 正确 obj_son = D()obj_son.show() # 派生类中可以访问   ==> 错误

普通字段

公有普通字段:对象可以访问;类内部可以访问;派生类中可以访问
私有普通字段:仅类内部可以访问
ps:如果想要强制访问私有字段,可以通过 【对象._类名私有字段明 】访问(如:obj._Cfoo),不建议强制访问私有成员。

class C:        def __init__(self):        self.__foo = "私有字段"     def func(self):        print(self.foo)  #类内部访问class D(C):    def show(self):        print(self.foo) #派生类中访问obj = C() obj.__foo     # 通过对象访问    ==> 错误obj.func()  # 类内部访问        ==> 正确 obj_son = D()obj_son.show()  # 派生类中访问  ==> 错误


特殊的类成员

#__init__构造方法,通过类创建对象时,自动触发执行#__del__析构方法,当对象在内存中被释放时,自动触发执行print(str.__module__)  #输出模块print(str.__class__)   #输出类


#特殊方式(type类的构造函数)创建类def func(self):    print('hello wupeiqi')Foo = type('Foo',(object,), {'func': func})Foo#type第一个参数:类名#type第二个参数:当前类的基类#type第三个参数:类的成员