一、对象的特有名称空间

__init__方法会在实例化对象时被调用

1、会为实例化的对象形成空的名称空间
2、就是一个方法,可以被传参,在类名(实参)这种方式下调用并传参 __init__(self 形参)
3、第一个self就是要产生的当前对象 重点:在方法内部,形参拿到了实参值,利用self.属性名 = 形参 = 实参值, 对对象的名称空间添加属性

class Student:

    # def __init__(self, name, sex):
    #     print('2>>>', self)
    #     self.name = name
    #     self.sex = sex

    # def fn():
    #     print('fn run ')

    def set_stu(stu, name, sex):
        stu.name = name
        stu.sex = sex

# print(Student.__dict__)
# Student.fn()    # fn run
stu1 = Student()
print(stu1.__dict__)   # {}

Student.set_stu(stu1, 'Bob', 'male')
print(stu1.__dict__)   # {'name': 'Bob', 'sex': 'male'}

print(stu1.name)   # Bob
print(stu1.sex)    # male

stu2 = Student()

Student.set_stu(stu2, 'Tom', 'female')
print(stu2.__dict__)   # {'name': 'Tom', 'sex': 'female'}
print(stu2.name, stu2.sex)     # Tom female

二、对象方法:

对象调用类的方法(类中方法的第一个默认参数:对象方法),建议使用对象调用

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

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

stu = Student('Bob')
stu.study()      # Bobstudy
stu2 = Student('Tom')
stu2.study()     # Tomstudy

# 类中方法的第一个默认参数:对象方法

# 总结:对象调用类的方法

class Student:
    pass
stu = Student()

def fn(a, b):
    print('fn run')
stu.fn = fn
stu.fn(, )    # fn run

class A:
    def test(self):
        print(self)
        pass
a = A()
a.test()                 # <__main__.A object at 0x0000000002767550>
A.test(a)                # <__main__.A object at 0x0000000002767550>
A.__dict__['test'](a)    # <__main__.A object at 0x0000000002767550>

三、类方法:

可以被类与对象调用的方法,第一个参数一定是类,类方法不建议拿对象来调用

class Tool:
    # 类自己的方法
    def add(cls, n1, n2):
        cls.fn()
        return n1 + n2

    def fn():
        pass

    # a如果被外界对象tool调用,那么内部调用b,b其实也是被外界对象tool调用的
    def a(self):
        self.b()
    def b(self):
        pass

res = Tool.add(Tool, , )  # 类调用,外界传入两个参数,内部接收到两个
print(res)    # 

# 问题:类的名字,对象都可以使用,但是出现了类与对象使用时,参数个数不一致
# tool = Tool()
# print(tool.add(, ))  # 对象调用,外界传入两个参数,内部接收到三个,第一个是对象本身

class Tool:
    def add(cls, n1, n2):
        return n1 + n2

print(Tool.add(Tool, , ))     #    # 类调用
tool = Tool()
print(tool.add(, ))         #   # 对象调用

class Tool:
    # 类方法:可以被类与对象调用的方法,第一个参数一定是类
    # 类方法不建议拿对象来调用
    @classmethod
    def add(cls, n1, n2):
        print(id(cls))     #
        cls.test()
        return n1 + n2

    @classmethod
    def test(cls):
        pass

print(Tool.add(, ))     #
tool = Tool()
print(tool.add(, ))   #
print(id(Tool), id(tool))   #  

# 对象调用所属类的类方法,默认第一个参数传入的是 对象.__class__ 就是所属类
print(tool.__class__)    # <class '__main__.Tool'>

四、属性与方法的总结

class OldBoy:

    # 属于类的属性
    name = '老男孩'

    # 属于对象的属性
    def __init__(self, name):
        self.name = name

    # 属于类的方法
    # 需求:获取机构的名字
    @classmethod
    def get_class_name(cls):
        return cls.name

    # 属于对象的方法
    # 需求:获取校区的名字
    @classmethod
    def get_school_nmae(cls):
        return cls.name

# 创建校区
shanghai = OldBoy('上海校区')
shenzhen = OldBoy('深圳校区')

# 类方法的使用:建议使用类调用
print(OldBoy.get_class_name())   # 老男孩

# 对象方法的使用:建议使用对象调用
print(shanghai.get_school_nmae())   # 老男孩
print(shenzhen.get_school_nmae())   # 老男孩

五、封装:(封装的终极奥义:明确地区分内外,对外是隐藏的,对内是开放的)

1、定义:

对外隐藏类中一些属性与方法的实现细节,封装(从字面意思理解)就是隐藏,隐藏指的是在类内部将一个属性藏起来 让类外部的使用者无法直接用到

封装(从字面意思理解)就是隐藏,隐藏指的是在类内部将一个属性藏起来
让类外部的使用者无法直接用到。在py中就是用__开头将一个属性藏起来.

补充说明:封装绝对不是单纯意义的隐藏
需知定义属性的目的就是为了让使用者去用,使用者要想使用类内部隐藏的属性
需要类的设计者在类内部开一个接口(定义一个方法),在该方法内访问隐藏的属性
使用者以后就通过该方法来“间接地”访问内部隐藏的属性
作为类的设计者可以在接口之上附加任意逻辑从而严格控制类的使用者对属性的操作

优点:外界不能直接访问,让内部的属性与方法具有安全保障

2、如何封装(封装语法)

封装的原理:把用__开头的名字更名为 _类名__变量名,所以直接通过 变量名 | __变量名就访问不到

对象属性的封装,对外提供接口

如何把属性隐藏起来,就在属性前面加上__开头(注意不要加__结尾)

①其实这种隐藏只是一种语法上的变形,对外不对内

class Foo:
    __x =            # _Foo__x=

    def __init__(self, y):
        self.__y = y     # self._Foo__y=y

    def __f1(self):      # _Foo__f1
        print('Foo.f1')

    def get_y(self):
        print(self.__y)  # print(self._Foo__y)

obj = Foo()

# print(obj.x)       # 报错
# print(obj.__x)     # 报错

print(obj._Foo__x)   #
print(obj._Foo__y)   #
obj._Foo__f1()       # Foo.f1
obj.get_y()          # 

②这种语法意义上变形,只在类定义阶段发生一次,类定义之后,新增的__开头的属性都没有变形的效果

Foo.__aa=
print(Foo.__dict__)

obj.__bb=
print(obj.__dict__)    # {, }

③如果父类不想让子类覆盖自己的方法,可以在方法名前加__开头

class Foo:
    def __f1(self):        # _Foo__f1
        print('Foo.f1')

    def f2(self):
        print('Foo.f2')
        self.__f1()        # obj._Foo__f1()

class Bar(Foo):
    def __f1(self):        # _Bar__f1
        print("Bar.f1")

obj = Bar()
obj.f2()
# 结果为:
# Foo.f2
# Foo.f1

3、为什么要用封装(封装的目的)

①封装数据属性的目的:把数据属性封装起来,然后需要开辟接口给类外部的使用者使用,

好处是:我们可以在接口之上添加控制逻辑,从而严格空间访问者对属性的操作

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

    def tell_info(self):
        # u=input('user>>: ').strip()
        # p=input('pwd>>: ').strip()
        # ':
        print(self.__name, self.__age)

    def set_info(self, name, age):
        if type(name) is not str:
            raise TypeError('用户名必须为str类型')
        if type(age) is not int:
            raise TypeError('年龄必须为int类型')
        self.__name = name
        self.__age = age

p = People()
p.tell_info()        # egon 

p.set_info()
p.tell_info()        # EGON 

②封装函数属性的目的:为了隔离复杂度

class ATM:
    def __card(self):
        print('插卡')

    def __auth(self):
        print('用户认证')

    def __input(self):
        print('输入取款金额')

    def __print_bill(self):
        print('打印账单')

    def __take_money(self):
        print('取款')

    def withdraw(self):
        self.__card()
        self.__auth()
        self.__input()
        self.__print_bill()
        self.__take_money()

obj = ATM()
obj.withdraw()

# 结果为:
# 插卡
# 用户认证
# 输入取款金额
# 打印账单
# 取款

4、封装特性:@property

①property是一种特殊的属性,访问它时会执行一段功能(函数)然后有返回值

②为什么要用:将一个类的函数定义成特性以后,对象再去使用的时候obj.name, 根本无法察觉自己的name是执行了一个函数然后计算出来的,

这种特性的使用方式遵循了统一访问的原则

③用法:

例题:

BMI指数(bmi是计算而来的,但很明显它听起来像是一个属性而非方法,如果我们将其做成一个属性,更便于理解)

成人的BMI数值:
过轻:低于18.
正常:18.5-23.9
过重:-
肥胖:-
非常肥胖, 高于32
  体质指数(BMI)=体重(kg)÷身高^(m)
  EX:70kg÷(1.75×1.75)=22.86

class People:
    def __init__(self, name, weight, height):
        self.name = name
        self.weight = weight
        self.height = height

    @property
    def bmi(self):
        return self.weight / (self.height * self.height)

egon = People(, 1.80)
print(egon.bmi)                   # 加上@property后,egon.bmi后不加括号,相当于调用了bmi()
                                  # 没有加上@property,要想运行,egon.bmi()

# 首先需要明确.bmi是算出来的,不是一个固定死的值,也就说我们必须编写一个功能,每次调用该功能都会立即计算一个值
egon = People(, 1.80)

# 但很明显人的bmi值听起来更像一个名词而非动词
print(egon.bmi())    # 会报错。egon.bmi后面加括号相当于是调用了bmi函数,但是bmi函数上被property装饰了之后
                     # ,bmi函数被伪装成一个数据属性了。

# 于是我们需要为bmi这个函数添加装饰器@property,将其伪装成一个数据属性
egon.weight =
print(egon.bmi)   # 调用egon.bmi本质就是触发函数bmi的执行,从而拿到其返回值

六、对象的属性方法封装与接口

1、对象的属性封装

①对象的属性值一般都来源于外界,外界是有权力再次访问的

②封装的目的不是让外界无法访问,而且不让其直接访问,可以在完成安全处理后再访问

③如何做到外界还是通过变量名来对属性进行取值赋值

-- __money被封装,外界还是可以通过 对象.money 取值赋值

2、对象的方法封装一般的实现需求都是,这些方法只在内部使用

# 对象的属性与方法封装集中与类的属性与方法封装原理一样
class AAA:
    def __init__(self, money):
        self.__money = money
        self.__id = 

    @property
    def id(self):
        return self.__id
    @id.setter
    def id(self, id):
        self.__id = id

    # 对象的属性封装
    # .对象的属性值一般都来源于外界,外界是有权力再次访问的
    # .封装的目的不是让外界无法访问,而且不让其直接访问,可以在完成安全处理后再访问
    # .如何做到外界还是通过变量名来对属性进行取值赋值
    #       -- __money被封装,外界还是可以通过 对象.money 取值赋值

    # 取值
    @property  # 在外界可以 对象.money 进行取值
    def money(self):
        # print('走方法拿到的money')
        return self.__money

    # 赋值
    @money.setter  # 在外界可以 对象.money = 新值 进行赋值
    def money(self, money):
        self.__money = money

    # 删除
    @money.deleter
    def money(self):
        # print('逗你玩')
        del self.__money

    def get_money(self, flag):
        if flag == '自家人':
            return self.__money

    def set_money(self, money):
        self.__money += money

    # 对象的方法封装一般的实现需求都是,这些方法只在内部使用
    def __test(self):
        print('test run')

a = AAA()

print(a.get_money(
a.set_money()
print(a.get_money(

print(a.money)                      #
a.money =
print(a.money)                      # 

七、绑定方法和非绑定方法

1、对象的绑定方法:有被任何装饰器装饰的方法

在类内部定义的函数,默认就是给对象来用,而且是绑定给对象用的,称为对象的绑定方法

绑定对象的方法特殊之处:应该由对象来调用,对象来调用,会自动将对象当作第一个参数传入self

2、类的绑定方法:用classmethod装饰器装饰的方法。

classmehtod是给类用的,即绑定到类,类在使用时会将类本身当做参数传给类方法的第一个参数

(即便是对象来调用也会将类当作第一个参数传入), python为我们内置了函数classmethod来把类中的函数定义成类方法

class People:
    country = 'china'

    def __init__(self, name):
        self.name = name

    def run(self):
        print('%s running...' % self.name)

    @classmethod
    def eat(cls, name):
        cls.name = name
        print(cls.name +' eating')

p1 = People('l_egon')

People.eat('egon')         # egon eating

3、非绑定方法:用staticmethod装饰器装饰的方法

特性:既不跟类绑定,也不跟对象绑定,这意味着谁都能用,谁来用都是一个普通函数,也就是说没有自动传值的特性了

class People:
    country = 'china'

    def __init__(self, name):
        self.name = name

    def run(self):
        print('%s running...' % self.name)

    @staticmethod
    def eat():        # 被装饰之后eat()就是一个普通的函数,
        print('eat')

p = People('tank')
p.eat()           # eat
People.eat()      # eat

day 23 二十三、对象方法,类方法,封装,绑定方法的更多相关文章

  1. 类的封装,property特性,类与对象的绑定方法和非绑定方法,

    类的封装 就是把数据或者方法封装起来 为什么要封装 封装数据的主要原因是:保护隐私 封装方法的主要原因是:隔离复杂度(快门就是傻瓜相机为傻瓜们提供的方法,该方法将内部复杂的照相功能都隐藏起来了,比如你 ...

  2. Python面向对象之封装、property特性、绑定方法与非绑定方法

    一.封装 ''' 1.什么封装 封:属性对外是隐藏的,但对内是开放的(对内是开放的是因为在类定义阶段这种隐藏已经发生改变) 装:申请一个名称空间,往里装入一系列名字/属性 2.为什么要封装 封装数据属 ...

  3. day22-类的封装、property特性以及绑定方法与非绑定方法

    目录 类的封装 两个层面的封装 第一个层面 第二个层面 封装的好处 私有模块 类的propertry特性 setter 和 deleter 类与对象的绑定方法与非绑定方法 类的封装 将类的属性或方法隐 ...

  4. 1.面向过程编程 2.面向对象编程 3.类和对象 4.python 创建类和对象 如何使用对象 5.属性的查找顺序 6.初始化函数 7.绑定方法 与非绑定方法

    1.面向过程编程 面向过程:一种编程思想在编写代码时 要时刻想着过程这个两个字过程指的是什么? 解决问题的步骤 流程,即第一步干什么 第二步干什么,其目的是将一个复杂的问题,拆分为若干的小的问题,按照 ...

  5. Python--多态与多态性、绑定方法与非绑定方法

    多态与多态性 多态 多态指的是一类事物有多种形态,(一个抽象类有多个子类,因而多态的概念依赖于继承) 1. 序列类型有多种形态:字符串,列表,元组. s='hello' l=[,,] t=('a',' ...

  6. python 类的绑定方法和非绑定方法

    一.绑定方法 1.对象的绑定方法 首先我们明确一个知识点,凡是类中的方法或函数,默认情况下都是绑定给对象使用的.下面,我们通过实例,来慢慢解析绑定方法的应用. class People: def __ ...

  7. Day 5-5 绑定方法与非绑定方法

    绑定方法与非绑定方法: 在类内部定义的绑定方法,分两大类: classmehtod是给类用的,即绑定到类,类在使用时会将类本身当做参数传给类方法的第一个参数(即便是对象来调用也会将类当作第一个参数传入 ...

  8. 全面解析python类的绑定方法与非绑定方法

    类中的方法有两类: 绑定方法 非绑定方法 一.绑定方法 1.对象的绑定方法 首先我们明确一个知识点,凡是类中的方法或函数,默认情况下都是绑定给对象使用的.下面,我们通过实例,来慢慢解析绑定方法的应用. ...

  9. python基础之多态与多态性、绑定方法和非绑定方法

    多态与多态性 多态 多态并不是一个新的知识 多态是指一类事物有多种形态,在类里就是指一个抽象类有多个子类,因而多态的概念依赖于继承 举个栗子:动物有多种形态,人.狗.猫.猪等,python的序列数据类 ...

随机推荐

  1. SpringBoot实战——微信点餐系统

    1.初始化项目 引入模块 <dependencies> <dependency> <groupId>org.springframework.boot</gro ...

  2. python跨网段遍历枚举IP地址(转)

    转载链接:https://blog.csdn.net/u013042248/article/details/53165508 0x01 代码思路: 利用二进制遍历: 1.将IP地址分割,每一块转换为8 ...

  3. VMware的NAT网络模式

    参考链接:https://www.cnblogs.com/linjiaxin/p/6476480.html 图例:

  4. MS SQL Server NULL处理

    -- 首先在用户表中插入数据如下 TRUNCATE TABLE UserInfo ; INSERT INTO userinfo(UserName,UserLogin,UserPassword,User ...

  5. 【原创】大叔经验分享(23)spark sql插入表时的文件个数研究

    spark sql执行insert overwrite table时,写到新表或者新分区的文件个数,有可能是200个,也有可能是任意个,为什么会有这种差别? 首先看一下spark sql执行inser ...

  6. 【原创】大叔问题定位分享(18)beeline连接spark thrift有时会卡住

    spark 2.1.1 beeline连接spark thrift之后,执行use database有时会卡住,而use database 在server端对应的是 setCurrentDatabas ...

  7. Mac OSX 系统搭建 Java 开发环境

    转载:https://www.cnblogs.com/zjx2711904647/p/7735556.html 1. 安装JDK 双击jdk-9.0.1_osx-x64_bin.dmg文件进行安装 2 ...

  8. CentOS7.X首次安装docker无法启动的问题解决

    CentOS7.2 随着Docker的不断流行与发展,docker公司(或称为组织)也开启了商业化之路,Docker 从 17.03版本之后分为 CE(Community Edition) 和 EE( ...

  9. java实现http请求

    String apiUrl = "https://api.seniverse.com/v3/weather/now.json?key=" + key + "&lo ...

  10. linux下安装redis并开机自启动

    分享一个博客地址, 写的太好了, 满满的都是干货 ! https://www.cnblogs.com/renzhicai/p/7773080.html