python类中self的问题?

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了python类中self的问题?相关的知识,希望对你有一定的参考价值。

问题设计python内核,以下代码在python运行时内存指向问题?
class test3:
count=0
def init(self):
test3.count += 1 #!!!注意此处不是self.count
#--------------------------------------------------#
cc3=test3()
cc3.init()
print(cc3.count) #返回1
cc4=test3()
cc4.init()
print(cc3.count,cc4.count) #返回2,2
cc4.count=6
cc4.init()
print(cc3.count,cc4.count) #返回3,6

我想问一问:

为什么第二次返回2,2 ?

为什么第三次返回3,6 ?

原因都出在第4行这句: test3.count += 1 #!!!注意此处不是self.count
你每运行一次 init() 函数 count 就会累加一
注意 你累加的是 test3.count 而不是 self.count
所以 运行了三次 init() 函数 的输出是 1 2 3
如果 你累加的是 self.count 就会输出三次 1 1 1
***首先要理解上面所说的 再继续看下面的***
既然如此 print(cc3.count,cc4.count) #返回2,2 就是正确的
cc3.count 指向的 test3().count 输出的是 2 没异议是吧
cc4.count 指向的也是 test3().count 为什么不是 2 都是同一个东西
print(cc3.count,cc4.count) #返回3,6
前面第一个3 就不用多说了
后面的第二个6 是因为你 cc4.count=6 这句指定了他是6
比如 a = 6 输出a会是什么? 当然是6啊
参考技术A Python编写类的时候,每个函数参数第一个参数都是self,一开始我不管它到底是干嘛的,只知道必须要写上。后来对Python渐渐熟悉了一点,再回头看self的概念,似乎有点弄明白了。

首先明确的是self只有在类的方法中才会有,独立的函数或方法是不必带有self的。self在定义类的方法时是必须有的,虽然在调用时不必传入相应的参数。

self名称不是必须的,在python中self不是关键词,你可以定义成a或b或其它名字都可以,但是约定成俗(为了和其他编程语言统一,减少理解难度),不要搞另类,大家会不明白的。

下例中将self改为myname一样没有错误:

class Person:
def _init_(myname,name):
myname.name=name
def sayhello(myname):
print 'My name is:',myname.name
p=Person('Bill')
print p
self指的是类实例对象本身(注意:不是类本身)。

class Person:
def _init_(self,name):
self.name=name
def sayhello(self):
print 'My name is:',self.name
p=Person('Bill')
print p
在上述例子中,self指向Person的实例p。 为什么不是指向类本身呢,如下例子:

class Person:
def _init_(self,name):
self.name=name
def sayhello(self):
print 'My name is:',self.name
p1=Person('Bill')
p2 = Person('Apple')
print p1
如果self指向类本身,那么当有多个实例对象时,self指向哪一个呢?

总结

self在定义时需要定义,但是在调用时会自动传入。

self的名字并不是规定死的,但是最好还是按照约定是用self

self总是指调用时的类的实例。追问

感谢回答。但是,你说的我都知道,我问的是为什么会有这些结果?运算过程中的内存指向。问题比较设计python语言的内核。

参考技术B

类中函数带上self,就可以调用你在初始化的时候所使用的变量

只在类中读取的Python属性

我有一节课:

class Portfolio:
    def __init__(self, value):
        self.value = value

class GenericStrategy:
    def __init__(self, portfolio: Portfolio):
        self.portfolio = portfolio

    def modify_ptf_value(new_value):
        self.portfolio.value = new_value
        # This should return an error

我会写一些将继承GenericStrategy的策略。我希望他们的方法能够读取属性组合但不能修改它,也不能修改它的属性。

我读了一些关于@properties装饰器的东西,但它只有在我不希望从外部访问属性(及其属性)时才有效,我仍然可以从对象里面的方法中修改属性(及其属性) 。有没有办法让属性(及其属性)'只读'除了__init__方法?我的设计是错的,应该重新开始吗?我知道用户不应修改“受保护”属性,但我想让它成为防弹。任何想法都被广泛接受,即使它需要在课堂设计上进行重大改变。

谢谢

答案

与其他(常用的)编程语言相反,Python提供了一种关于访问类/实例成员的新方法。例如,没有什么是真正的私有,字段/方法:

  • _开始,是常规领域
  • __开始(最多只有一个_),只是名称被破坏,但它们仍然可以从课外访问(甚至修改/删除)

所以,最后这是一个约定问题,它依赖于编写代码的人。最重要的是,没有任何东西可以阻止用户访问类/实例的内部。

注意:在其他语言中,也可以访问私有成员:有正式支持的方法(如Java的反射([Oracle]: Trail: The Reflection API)),或者不那么官方支持(需要一些“技巧” - 例如:reinterpret_casting a class to a struct with与C ++相同的结构)。如今,越来越多的语言倾向于提供一种改变实例结构的方法。

无论如何,有一个所谓的描述符协议([Python]: Descriptor HowTo Guide),它是Python最强大(也是最容易被误解)的功能之一。

使用描述符(作为旁注,属性依赖于它们),我写了一段代码,在某种程度上实现了你所要求的:

class LockedAttribute(object):
    def __init__(self, name):
        self._name = name
        self._set_count = 0
        self._set_treshold = 1

    def __get__(self, instance, cls):
        return instance.__dict__[self._name]

    def __set__(self, instance, value):
        if self._set_count >= self._set_treshold:
            raise AttributeError("Can't set attribute '{}'".format(self._name))
        else:
            instance.__dict__[self._name] = value
            self._set_count += 1

    def __delete__(self, instance):
        raise AttributeError("Can't delete attribute '{}'".format(self._name))


class GenericStrategy(object):
    portfolio = LockedAttribute("portfolio")

    def __init__(self, portfolio):
        self.portfolio = portfolio
        try:
            self.portfolio = portfolio
        except AttributeError as e:
            print("  ERROR: {}".format(e))

    def set_portfolio(self, new_value):
        self.portfolio = new_value


if __name__ == "__main__":
    strategy = GenericStrategy("some portfolio name")
    print("Portfolio: {}".format(strategy.portfolio))
    try:
        del strategy.portfolio
    except AttributeError as e:
        print("  ERROR: {}".format(e))
    try:
        strategy.set_portfolio("some 2nd portfolio name")
    except AttributeError as e:
        print("  ERROR: {}".format(e))
    try:
        strategy.portfolio = "some 3rd portfolio name"
    except AttributeError as e:
        print("  ERROR: {}".format(e))
    print("Portfolio: {}".format(strategy.portfolio))

笔记:

  • 我从私有属性的名称(__)中删除了portfolio,以避免在我的代码中使用我正在谈论的修改(会使其更难阅读)
  • 对于Py27兼容性,类继承object。如果兼容性不是必需的,则可以删除继承关系(在Py3x中默认情况下)
  • 我添加了try/except块来说明行为,在生产中它们应该被删除
  • 如上所述,如果有人想改变这种行为,可以

以上是关于python类中self的问题?的主要内容,如果未能解决你的问题,请参考以下文章

Python类中self的作用

Python类中的self到底是干啥的

Python类中的self到底是干啥的

Python类中的self到底是干啥的

python中的self

python类中的self参数和cls参数