python内部类调用外部类中同一个类的属性可以调用自身的方法吗

  在上篇的时候,我们知道了:属性就是属于一个对象的数据或者函数,我们可以通过句点(.)来访问属性,同时 python 还支持在运作中添加和修改属性。
  而数据变量,类似于:&name = 'scolia' 这样的形式,会称其为字段;而类里面的函数,又称为方法。而方法又分为实例方法,类方法和静态方法,这些我们以后在讲。
  我们先来看看类里面的普通字段:
class Test(object):
name = 'scolia'
a = Test()
print Test.name
# 通过类进行访问
print a.name
# 通过实例进行访问
  我们发现都是可以访问的。
  但是,如果我们试图修改这个属性的话:
class Test(object):
name = 'scolia'
a = Test()
Test.name = 'scolia good'
# 通过类进行修改
print Test.name
print a.name
  我们发现两者都修改成功了。
  如果通过实例来修改属性的话:
class Test(object):
name = 'scolia'
a = Test()
a.name = 'scolia good'
# 通过实例进行修改
print Test.name
print a.name
  我们发现类的属性没有修改,而实例的属性则修改成功了。这究竟是为什么?
  其实这里的情况非常类似于局部作用域和全局作用域。
  我在函数内访问变量时,会先在函数内部查询有没有这个变量,如果没有,就到外层中找。这里的情况是我在实例中访问一个属性,但是我实例中没有,我就试图去创建我的类中寻找有没有这个属性。找到了,就有,没找到,就抛出异常。而当我试图用实例去修改一个在类中不可变的属性的时候,我实际上并没有修改,而是在我的实例中创建了这个属性。而当我再次访问这个属性的时候,我实例中有,就不用去类中寻找了。
  如果用一张图来表示的话:
  函数 &dir()& 就能查看对象的属性:
class Test(object):
name = 'scolia'
a = Test()
a.abc = 123
print dir(Test)
print dir(a)
  它返回一个列表,包含所有能找到的属性的名字,这里我们为实例 a 创建了 abc 属性,这里就能看到了。
  有些同学会有疑问,为什么我才写了几个属性,结果却多出一堆我不认识的?
  因为我们这里用的是新式类,新式类继承于父类 object ,而这些我们没有写的属性,都是在 object 中定义的。
  如果我们用经典类的话:
  为了方便演示,下面都使用经典类,若没有特殊说明,新旧两式基本是一样的。
  其中 __doc__ 是说明文档,在类中的第一个没有赋值的字符串就是说明文档,一般在class的第二行写,没有就为 None。
   __module__ 表示这个类来自哪个模块,我们在主文件中写的类,其值应该为 &__main__&,在其他模块中的类,其值就为模块名。
class Test:
"""文档字符串"""
name = 'scolia'
print Test.__doc__
print Test.__module__
  文档字符串不一定非要用三引号,只是一般习惯上用三引号表示注释。实例也可以访问,实际访问的是创建它的类的文档字符串,但是子类并不会继承父类的文档字符串,关于继承的问题以后再讲。
  除了这两个特殊的属性之外,还有几个常用的,虽然没有显示出来,但也是可以用的。
&__dict__&
class Test:
"""文档字符串"""
name = 'scolia'
a = Test()
a.name = 'good'
print Test.__dict__
print a.__dict__
  这个属性就是将对象内的属性和值用字典的方式显示出来。这里可以明显的看出来,实例创建了一个同名的属性。
  我们也可以使用 &vars()& 函数,传给函数一个对象,其结果也是一样的。
&__class__&
class Test:
a = Test()
print a.__class__
  这个属性只有实例中有,它表示创建这个实例的类是哪个,这里显示是 __main__ 模块,也就是主文件中的 Test 这个类创建的。
  但是其返回值并不是字符串,而是创建实例的类对象,但新旧式类返回有点不同:
  因为返回的是创建实例的类对象,也就是说我们也要用这个返回的类对象再进行实例化。
b = a.__class__()
  这里用的是新式类为例,实际上新旧式类都能这样做。下面是旧式类的:
  但是,这并不意味不能通过实例来修改类中的属性。我们知道对于不可修改类型的&修改&,其实就是重新赋值。这个也和函数中的局部作用域和全局作用域类似,我在函数内部尝试&修改&一个不可变类型其实就是创建新的同名变量。但我却可以访问全局某个可修改的对象来修改它。
  看代码:
class Test:
list1 = []
a = Test()
a.list1.append(123)
# 同通过实例修改类中的列表
print Test.list1
print a.list1
  我通过实例访问到了一个对象,这个对象是可修改的,所以我可以修改这个对象。这相当于直接操作那个对象。
  但是,等号这样的显式赋值行为还是创建新的对象:
a.list1 = [123]
# 显式的创建一个新对象
  这可能有点绕,需要对变量的赋值、可修改对象与不可修改对象的了解,可以参考我以前的相关博文。
  这里又有个问题了,我们通常使用 __init__ 来初始化时,会为其添加数据属性,例如 self.name = xxx ,但是却几乎不会为实例添加方法,也就是说实例中的方法,都是在类中找的。这样做其实有好处,因为方法一般是通用的,如果每一个实例都要保存一套方法的话,实在太浪费资源,而把这些方法统一保存到类中,用到的时候来类里找,就节约了许多。
  当然,我们也可以任性地为某个实例添加方法,python 支持动态添加属性。
class Test:
def fangfa():
print '我是某个实例的方法'
a = Test()
b = Test()
a.abc = fangfa
# 特意添加一个方法
# b 没有这个方法
  同样的,我们也可以为类动态添加一个方法:
class Test:
def fangfa(self):
# self 代表是实例方法,只能由实例调用
print '我是方法'
Test.abc = fangfa
a = Test()
  关于方法以后再细说。
  当然一般情况下我们很少这样做,因为这样会变得不可控,因为你不知道某个方法在你调用的时候有没有创建。
字段私有化:
  我们可以对属性进行私有化,以限制部分访问,但关于方法私有化以后在讲,现在先说说字段私有化。
  一般公有字段我们可以通过实例对象访问,类对象访问,类里面的方法也可以访问。
  而私有字段一般仅类里面的方法可以访问了。
  私有化的方法非常简单,只需要在变量名前面加上两个下划线即可:
class Test:
__name = 'scolia'
# 私有字段
def a(self):
print Test.__name
#内部还需要用类来方问
a = Test()
print Test.__name
# 在外部使用类来访问
  我们可以看到在外部通过类来访问是不行的,但内部通过类来访问却可以。
  同样的,通过实例访问也不允许。
print a.__name
  但是,私有化并不是语法上的强制,而是 python 隐藏了私有字段的访问入口,所以我们可以在新的入口中访问到私有字段:
print Test._Test__name
  其格式是: 对象._类__字段名;这里是类的私有字段,所以使用的对象是类对象。
  上面的代码使用的是类对象,也可以使用实例对象进行访问&a._Test__name&。
  私有化其实就是&混淆&了相应的属性,这样做还有一个好处,可以保护 __xxx 变量不会与父类中的同名变量冲突。如果父类中有也有一个 __xxx 的变量的话,父类中的变量不会被子类中 __xxx 覆盖。如果是非私有的字段 xxx ,就会被子类中的覆盖掉。所以私有化也是保护关键变量的好选择。
  我们上面讲的都是类中的字段的私有化,同样的,我们也可以为实例的字段进行私有化。
class Test:
def __init__(self):
self.__name = 'scolia'
# 实例的私有字段
def a(self):
print self.__name
# 只能有内部方法能访问
a = Test()
print a.__name
# 试图通过实例访问
  当然,因为实例属性类中并没有,所以不用考虑通过类来访问了。
  同样的,这里也是隐藏了入口,访问格式依然是一样的,只不过这里的对象指的是实例了。
print a._Test__name
  总结:公用字段可以通过类对象,实例对象,类里面的方法进行访问。
     而私有字段则一般通过类里面的方法进行访问。
    && 一般不建议强制访问私有字段。
  关于类中的字段,和其私有化就先将这么多,以后有需要再补充。
阅读(...) 评论()MethodType绑定到类和把方法直接写到类里有什么不同?【python吧】_百度贴吧
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&签到排名:今日本吧第个签到,本吧因你更精彩,明天继续来努力!
本吧签到人数:0成为超级会员,使用一键签到本月漏签0次!成为超级会员,赠送8张补签卡连续签到:天&&累计签到:天超级会员单次开通12个月以上,赠送连续签到卡3张
关注:190,073贴子:
MethodType绑定到类和把方法直接写到类里有什么不同?收藏
一、使用MethodType给类绑定一个方法class Stu(object):
pass def set_age(self,age):
self.age=age from types import MethodTypeStu.set_age=MethodType(set_age,Stu) A=Stu() B=Stu()A.set_age(10)B.set_age(15)print(A.age,B.age)#结果都是15上面的例子为什么都是15,解释说实例A和实例B都没有age属性,原本的就是A.set_age就是给Stu类绑定属性age,给Stu绑定类属性为什么不是Stu.set_age(15)这样的方式?而是以实例A.set_age开头?二、在类内部定义一个方法class Student(object):
def set_age(self,age):
self.age=ageA=Student()B=Student()A.set_age(10)B.set_age(15)print(A.age,B.age)#结果是10和15MethodType是将方法绑定到实例或者类,教程里也说过绑定类一般都会把方法写进去,原话是这样的:“给class绑定方法后,所有实例均可调用,通常情况下,上面的方法可以直接定义在class中”这句话我理解的就是MethodType就相当于把方法直接写进class中,为什么会出现上面两种结果,求解释。MethodType绑定的方法和类内部定义的方法有什么区别?
登录百度帐号【Python】类的属性和方法的参数加不加self的区别
先看一段代码
class Test(object):
def __init__(self):
def prtID(self):
print(self.ID)
def classplusOne(self):
Test.ID += 1
def ObjplusOne(self):
self.ID += 1
t1 = Test()
t2 = Test()
t1.classplusOne()这里会发现t1对ID进行了修改却影响了t2的ID, 这就说明ID属于Test类,而非它的对象,换句话说这个属性是全体Test实例共用的。这是因为self的意思同c++的this指针,它代表了类当前的实例,所以加了self的属性就是类实例的属性,不加就是类的属性,这同c++中静态类变量的含义是一样的。
没有更多推荐了,python类的属性、方法和内置方法
1、对象的创建
创建对象的过程称之为实例化;当一个对象被创建后,包含三个方面的特性:对象句柄、属性和方法。
句柄用于区分不同的对象
对象的属性和方法与类中的成员变量和成员函数对应
obj=MyClass() //创建类的一个实例(对象)通过对象来调用方法和属性
2、类的属性
类的属性按使用范围:公有属性和私有属性,
类的属性范围取决于属性的名称。
公有属性:在类中和类外都能调用属性。
私有属性:不能在类外及被类意外的函数调用。
定义方式:以“_”双下划线开始的成员变量就是私有属性
私有属性,可以通过instance._classname_attribute方式访问。
内置属性:有系统在定义类的时候默认添加的,由前后双下划线构成,dict,module.
class People(object):
color = "yellow"
__age = 30
def think(self):
self.color = "black"
print ("I am a %s" %self.color)
ren = People()
print ren.color
ren.think()
print ren._People__age
3、类的方法
方法的定义和函数一样,但是需要self作为第一个参数
类的方法为:
公有方法:在类中和类外都能调用的方法
私有方法:不能被类外部调用,在方法前面加上“__“双下划线就是私有方法;
类方法:被classmethod()函数处理过的函数,能被类所调用,也能被对象所调用(是继承的关系)
静态方法:相当于“全局函数”,可以被类直接调用,可以被所有实例化对象共享,通过staticmethod()定义,
静态方法没有“self”参数。
用于区分函数和类的方法(必须有一个self),self参数表示执行对象本身。
- @classmethod
- @staticmethod
class People(object):
color = "yellow"
__age = 30
def think(self):
self.color = "black"
print ("I am a %s" %self.color)
print self.__age
def __talk(self):
print("I am talking with Tom")
@classmethod
#装饰器,只对下面的一个函数起作用
def test(self):
print("this is class method")
@staticmethod
#装饰器,只对下面的一个函数起作用
def test1():
print ("this is static method")
David = People()
People.test()
People.test1()
4、python内部类
所谓的内部类,就是在类的内部定义的类(类的嵌套),主要目的是为了更好的抽象现实世界。
内部类的实例化方法
方法1:直接使用外部类调用内部类
object_name=outclass_name.inclass_name()
jack=People.Chinese() #People是外部类,Chinese是内部类
方法2:先对外部类进行实例化,然后在实例化内部类
out_name=outclass_name()
in_name=out_name.inclass_name()
in_name.method()
ren=People()
#People是外部类
jack=ren.Chinese()
#Chinese是内部类
print jack.name
构造函数与析构函数
用于初始化类的内部状态,Python提供的构造函数是init();
init()方法是可选的,如果不提供,Python会给出一个默认的的init方法
用于释放对象占用的资源,Python提供的析构函数是del();
del()也是可选的,如果不提供,则Python会在后台提供默认析构函数
垃圾回收机制
Python采用垃圾回收机制来清理不再使用的对象;Python提供gc模块释放不再使用的对象。
Python采用“引用计数”的算法方式来处理回收,即:当某个对象在其作用域内不再被其它对象引用的时候,Python就自动清除对象;
gc模块的collect()可以一次性收集所有待处理的对象(gc.collect)
class People(object):
color = 'yellow'
__age = 20
class Chinese(object):
name = "I am chinese"
def __str__(self):
return "This is People class"
def __init__(self):
self.color = 'black'
def __del__(self):
print "Del……"
self.fd.close()
print gc.collect()
jack = People()
print jack.color
print People.color
print 'Main end'
没有更多推荐了,在Python中,一个类中方法的返回值可不可以是另外一个类呢?_百度知道
在Python中,一个类中方法的返回值可不可以是另外一个类呢?
比如说:有宠物.小狗()
和 狗类动物.毛色(),这两个类的方法。我的狗=宠物.小狗()#返回值为狗类动物类我的狗.毛色=黄色可不可以这样做呢?只要回答可不可以就行。
我有更好的答案
当然可以了。Python中有个元类的概念, metaclass就是用来生成类的类。还有工厂函数的概念,就是说一个函数直接返回一个类。class&MetaDog:&&&&def&__init__(self,&color=''):&&&&&&&&self.color&=&color&&&&def&show_color(self):&&&&&&&&print('my&dog&color&is&{}.'.format(self.color))class&Animal:&&&&def&dog_class(self):&&&&&&&&return&MetaDoganimal&=&Animal()Dog&=&animal.dog_class()my_dog&=&Dog()my_dog.color&=&'yellow'#&my_dog&=&Dog('yellow')my_dog.show_color()#&my&dog&color&is&yellow.
采纳率:76%
为您推荐:
其他类似问题
换一换
回答问题,赢新手礼包
个人、企业类
违法有害信息,请在下方选择后提交
色情、暴力
我们会通过消息、邮箱等方式尽快将举报结果通知您。}

我要回帖

更多关于 python调用类方法 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信