Python之面向对象

C#   Java:只能面向对象编程

Ruby   Python :面向对象编程+函数编程

在Python中一切皆对象

反射:以字符串的形式去对象中操作成员

tar_module = __import__( 'module_name' )  # 以字符串的形式导入某个模块

tar_module = __import__( ' lib.test.module_name ' , fromlist=True )  # 对于存在多层目录的模块导入方法

getattr( object,name )  获取某个对象中的某个成员,例如获取test.py中的f1方法,tar_func = getattr( test , 'f1' )

hasattr( object,name )  判断某个对象中是否存在某个成员,如果存在返回True,如果不存在返回False

delattr( object,name)  删除某个对象的某个成员

setattr( object,name)  设置某个对象中的某个成员,不存在该成员则创建,存在则覆盖

成员代指的属性或方法

注:上述所有操作均只生效于内存中,并不会对文件产生影响。例如你import了某个module,你使用delattr方法删除了其中某个方法,在本次程序运行期间,删除是有效的,但并不会真正删除该模块中的方法

基于反射实现Web框架的路由系统:用户访问某个URL-->后台接收该URL并判断调用哪个函数来处理该请求-->返回请求的页面

 

from temp import view

ref_dict = {'jack': 'f1', 'rose': 'f2', 'index': 'f3'}
url = input('请输入一个URL')
try:
    func = getattr(view, ref_dict[url])
    func()
except KeyError:
    print('wrong url')

 

def f1():
    print('this is jack')


def f2():
    print('this is rose')


def f3():
    print('this is index')

 

实例化一个对象后,其中存在一个 类对象指针 指向创建其的类,当对象调用方法时,自动去指针指向的类寻找方法

创建类和对象:

 

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

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

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

# 定义一个类
class Man:
    
    # 定义一个类的方法,传入的self为实例化的对象,通过对象来调用方法
    def eat(self):
        print('eat something')

jack = Man()  # 类的实例,一个对象

 

诶,你在这里是不是有疑问了?使用函数式编程和面向对象编程方式来执行一个“方法”时函数要比面向对象简便

 

  • 面向对象:【创建对象】【通过对象执行方法】
  • 函数编程:【执行函数】

观察上述对比答案则是肯定的,然后并非绝对,场景的不同适合其的编程方式也不同。

总结:函数式的应用场景 --> 各个函数之间是独立且无共用的数据

面向对象的三大特性:

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

 

一、封装

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

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

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

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

 

class Man:
    # 构造函数,当实例化一个对象时自动调用该方法
    def __init__(self, name, sex):
        self.name = name
        self.sex = sex

    def marrid(self):
        self.wife = 'rose'

# 将'jack'  'man' 分别封装到jack对象的name属性和sex属性
# 自动执行Man类__init__方法
jack = Man('jack', 'man')

# 获取jack的name属性
print(jack.name)

# 通过对象调用类的方法
jack.marrid()
print(jack.wife)


二、继承

 

# 父类,Animal
class Animal:
    # 构造方法,设置动物的名字和种类
    def __init__(self, ani_type, name):
        self.name = name
        self.ani_type = ani_type

   def eat(self):
        print('{}eat something'.format(self.name))

    def walk(self):
        print('{}walk away'.format(self.name))

    def drink(self):
        print('{}drink water'.format(self.name))

# 子类
class cat(Animal):
    pass

# 实例化一个cat对象,调用父类的构造方法
mimi = cat('cat', 'mimi')
# 调用父类的eat方法
mimi.eat()

 

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

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

还支持这样的操作:

 

class Animal():

    def eat(self):
        print(self.name+'eat')


class Dog(Animal):
    def __init__(self, name):
        self.name = name

    def drink(self):
        print('dog\'s drking')

hu = Dog('胖虎')
hu.eat()
hu.drink()

在父类Animal中并没有定义name这个字段,但是父类的方法中用到了这个字段。这时如果实例化子类并且定义了该字段的话,可以调用父类的方法,不会报错

 

 

 

 

 

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

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

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

2、python3的类都是新式类,即所有类的父类为object

对于多继承,查找方式如下:

1、多重继承,但没有共同的父类

 

class Son(A, D):  # 优先查找Son自己的方法,然后找A及A的父类,再找D及D的父类
    pass

class A(B):
    pass

class B(C):
    pass

class D(E):
    pass

class E(F):
    pass

 

子类继承A,A继承B,B继承C。子类还继承D,D继承E,E继承F。那么当需要调用一个方法时,优先从子类自身去找这个方法,如果不存在,查找顺序如下:

                                                                           图     1

2.多重继承,有共同的父类:

如果C和F共同继承于G,那么查找顺序依然如上图所示,最后去G中寻找

注意:在上述查找过程中,一旦找到,则寻找过程立即中断,便不会再继续找了

3.特殊情况:

                                                      图     2

代码:

class C:
    def do_something(self):
        print('这是C中的方法')
    pass


class B(C):
    def do_something(self):
        print('这是B中的方法')
    pass


class E:
    def do_something(self):
        print('这是E中的方法')
    pass


class D(E):
    def func(self):
        self.do_something()

    def do_something(self):
        print('这是D中的方法')
    pass


class A(B, D):
    def do_something(self):
        print('这是A中的方法')
    pass

a = A()
a.func()

 

 

 

A继承于B,D。D中有一个方法func(),调用了self.do_something方法,如果A中存在do_something方法,自然会调用A中的该方法,

那么如果A中不存在该方法呢?会调用哪个父类的do_something方法呢?这时我们需要注意的是,我们实例化的是一个A类的对象

a,传递进func的self指向的是a对象,那么调用self.do_something方法相当于是调用a对象的该方法。此时如果该方法不存在,应该

遵循 图 1 中的调用顺序。
深度优先遍历

三、多态 

 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

总结:

 

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

  • 面向对象是一种编程方式,此编程方式的实现是基于对  和 对象 的使用
  • 类 是一个模板,模板中包装了多个“函数”供使用
  • 对象,根据模板创建的实例(即:对象),实例用于调用被包装在类中的函数
  • 面向对象三大特性:封装、继承和多态

问题一:什么样的代码才是面向对象?

答:从简单来说,如果程序中的所有功能都是用 类 和 对象 来实现,那么就是面向对象编程了。

问题二:函数式编程 和 面向对象 如何选择?分别在什么情况下使用?

答:须知:对于 C# 和 Java 程序员来说不存在这个问题,因为该两门语言只支持面向对象编程(不支持函数式编程)。而对于 Python 和 PHP 等语言却同时支持两种编程方式,且函数式编程能完成的操作,面向对象都可以实现;而面向对象的能完成的操作,函数式编程不行(函数式编程无法实现面向对象的封装功能)。

所以,一般在Python开发中,全部使用面向对象面向对象和函数式混合使用

面向对象的应用场景:

1.多函数需使用共同的值,如:数据库的增、删、改、查操作都需要连接数据库字符串、主机名、用户名和密码

 

 

 

class SqlHelper:

    def __init__(self, host, user, pwd):

        self.host = host
        self.user = user
        self.pwd = pwd

    def 增(self):
        # 使用主机名、用户名、密码(self.host 、self.user 、self.pwd)打开数据库连接
        # do something
        # 关闭数据库连接

    def 删(self):
        # 使用主机名、用户名、密码(self.host 、self.user 、self.pwd)打开数据库连接
        # do something
        # 关闭数据库连接

    def 改(self):
        # 使用主机名、用户名、密码(self.host 、self.user 、self.pwd)打开数据库连接
        # do something
        # 关闭数据库连接

    def 查(self):
    # 使用主机名、用户名、密码(self.host 、self.user 、self.pwd)打开数据库连接
        # do something
        # 关闭数据库连接# do something

 

 

 

2.需要创建多个事物,每个事物属性个数相同,但是值的需求
如:张三、李四、杨五,他们都有姓名、年龄、血型,但其都是不相同。即:属性个数相同,但值不相同

 

class Person:

    def __init__(self, name ,age ,blood_type):

        self.name = name
        self.age = age
        self.blood_type = blood_type


    def detail(self):
        temp = "i am %s, age %s , blood type %s " % (self.name, self.age, self.blood_type)
        print temp

zhangsan = Person('张三', 18, 'A')
lisi = Person('李四', 73, 'AB')
yangwu = Person('杨五', 84, 'A')

 

 

 

问题三:类和对象在内存中是如何保存?

答:类以及类中的方法在内存中只有一份,而根据类创建的每一个对象都在内存中需要存一份,大致如下图:

 

 

 

如上图所示,根据类创建对象时,对象中除了封装 name 和 age 的值之外,还会保存一个类对象指针,该值指向当前对象的类。

当通过 obj1 执行 【方法一】 时,过程如下:

  1. 根据当前对象中的 类对象指针 找到类中的方法
  2. 将对象 obj1 当作参数传给 方法的第一个参数 self

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值