【问题标题】:Global variable is not being edited by function全局变量未被函数编辑
【发布时间】:2018-02-04 04:14:02
【问题描述】:

我已经尽我所能在代码中放置global user,看看它是否丢失了,但似乎没有。基本上,当我在此处看到的这段代码中分配全局 user 变量后调用 userInstance.getName() 时:

if(userName in nameList):
    for userdata in pklList:
        if userdata.getName() == userName:
            global user
            user = userdata
            print("user data found for user: " + user.getName())

它似乎并没有真正进入全局变量。这是目前代码的完整版本:

import praw
import time
import re
import pickle
from classes import User



USERAGENT = 'web:CredibilityBot:v0.1 (by /u/ThePeskyWabbit)'
FOOTER = "^^I ^^am ^^a ^^bot! ^^I ^^am ^^currently ^^in ^^test ^^phase. ^^Read ^^about ^^me ^^[here](https://pastebin.com/jb4kBTcS)."
PATH = "C:\\Users\\JoshLaptop\\PycharmProjects\\practice\\commented.txt"
user = User.User("ERROR")

commentFile = open(PATH, 'rb')
commentList = commentFile.read().splitlines()
commentFile.close()

pkl = open("userpkl.pkl", 'rb')
pklList = []
print(pklList)

try:
    pickle.load(pkl)
    while(True):
        pklList.append(pickle.load(pkl))
except EOFError:
    pass
pkl.close()

nameList = []
try:
    for data in pklList:
        nameList.append(str(data.getName()))
except:
    pass

print(pklList)
print(nameList)


def addPoint(comment):
    message = "current name for user: " + user.getName()
    #userInstance.addScore()
    #userInstance.addComment(comment)
    #message = "Bullshit noted! " + userInstance.getName() + " now has a Bullshit rating of " + userInstance.getScore() + "\n\n" + FOOTER
    return message

def getRating():
    message = user.getName() + " has a Bullshit rating of: " + user.getScore()
    return message

def getCommentList():
    bullshitComments = user.getComments()
    return bullshitComments



auth = True
def authenticate():
    print("Authenticating...")
    reddit = praw.Reddit('bot1', user_agent=USERAGENT)
    print("Authenticated as {}\n" .format(reddit.user.me()))
    return reddit

commentLink = None

actions = {"!bullshit": addPoint(commentLink), "!bullshitrating": getRating(user), "!bullshitdetail":getCommentList(user)}
stringList = ["!bullshit", "!bullshitrating", "!bullshitdetail"]

while(auth):
    try:
        reddit = authenticate()
        auth = False
    except:
        print("Authentication Failed, retying in 30 seconds.")
        time.sleep(30)


def runBot():
    SUBREDDITS = 'test'
    global user

    while(True):
        print("Scraping 1000 comments...")
        for comment in reddit.subreddit(SUBREDDITS).comments(limit=1000):

            for word in stringList:
                match = re.findall(word, comment.body.lower())

                if match:
                    id = comment.id
                    commentFile = open(PATH, 'r')
                    commentList = commentFile.read().splitlines()
                    commentFile.close()

                    if(id not in commentList):

                        print(match[0] + " found in comment: " + "www.reddit.com"  + str(comment.permalink()))
                        commentLink = "www.reddt.com" + str(comment.parent().permalink())
                        print("Bullshit comment is: " + commentLink)

                        print("searching for user data")
                        userName = str(comment.parent().author)
                        flag = True

                        if(userName in nameList):
                            for userdata in pklList:
                                if userdata.getName() == userName:
                                    user = userdata
                                    print("user data found for user: " + user.getName())


                        elif comment.parent().author is not None:
                            print("no user found, creating user " + userName)
                            user = User.User(userName)
                            f = open("userpkl.pkl", 'ab')
                            pickle.dump(user, f)
                            f.close()
                            nameList.append(userName)
                            print("added to user to pkl file")

                        else:
                            print("username could not be retrieved.")
                            print("adding ID to log\n")
                            commentFile = open(PATH, 'a')
                            commentFile.write(id + "\n")
                            commentFile.close()
                            flag = False

                        if(flag):
                            try:
                                print(actions[match[0]])
                                #print("sending reply...")
                                #comment.reply(actions[match[0]])
                                #print("Reply successful. Adding comment ID to log\n")
                                #commentFile = open(PATH, 'a')
                                #commentFile.write(id + "\n")
                                #commentFile.close()

                            except:
                                print("Comment reply failed!\n")




runBot()

奇怪的是,当我在上述代码片段中调用 user.getName() 时,它会输出正确的名称,而不是像我在 addPoint() 函数中调用它时那样输出“错误”。

打印语句输出如下:

C:\Python36-32\python.exe C:/Users/JoshLaptop/PycharmProjects/practice/TestBot.py
[]
[<classes.User.User object at 0x03B59830>, <classes.User.User object at 0x03816430>]
['PyschoWolf', 'ThePeskyWabbit']
Authenticating...
Authenticated as CredibilityBot

Scraping 1000 comments...
!bullshit found in comment: link deleted for privacy
Bullshit comment is: link deleted for privacy
searching for user data
user data found for user: PyschoWolf
current name for user: ERROR
!bullshit found in comment: link deleted for privacy
Bullshit comment is: link deleted for privacy
searching for user data
user data found for user: ThePeskyWabbit
current name for user: ERROR

【问题讨论】:

  • “错误”从何而来?我在代码中看不到输出“错误”的任何地方。如果您收到错误消息,请显示它。您确定在尝试使用之前初始化user 吗?尝试在程序顶部附近的外部代码中对其进行初始化。
  • 来自user.getName() 代码顶部行中分配的默认名称是“ERROR”
  • 这有点棘手,因为我要从 pickle 文件中加载对象以及使用 reddit 服务器验证帐户,然后从 .ini 文件中读取数据来执行此操作。我将尝试编写一些代码来创建此问题,而不需要我正在使用的文件。
  • 我在搜索“错误”(如您所写)而不是“错误”。

标签: python loops variables syntax global


【解决方案1】:

在 python 中,如果您的代码对变量进行赋值,那么除非明确说明,否则假定该变量是局部变量。如果您明确声明它们,它们将是全局的。

然而,全局变量是“每个模块”。

通常不清楚的是,当您导入名称时,会在当前模块中将导入的 value 复制为具有相同名称(或如果还使用as,则使用不同的名称。例如:

from xxx import user
# xxx.user has been copied to a globl named user

user = "baz"  # <--- this DOES NOT change xxx.user

xxx.user = "ohyeah"  # Now it changes xxx.user

请注意,Python 中对此有一些“神奇”之处,那就是函数会记住它们是在哪个模块中定义的。假设我有:

# module.py

user = "No user yet"

def setUser(newUser):
    global user
    user = newUser

def getUser():
    return user

# program.py
from module import user, setUser, getUser

print(user)      # --> "No user yet"
print(getUser()) # --> "No user yet"

setUser("Hey")

print(user)      # --> "No user yet" (1)
print(getUser()) # --> "Hey"

user = "Foo"
print(user)      # --> "Foo"
print(getUser()) # --> "Hey" (2)

(1) 发生是因为 user 只是程序的全局变量,而不是模块的全局变量。该值在导入时从模块复制到程序中,仅此而已

(2) 出于同样的原因发生。在模块中编译的代码将被视为该模块的全局变量,而不是程序。尽管在程序中进行了调用并且getUser 变量(包含函数)在此处,但仍会发生这种情况。它是“记住”它应该访问的全局变量的函数。

代码

from xxx import yyy

相同
import xxx
yyy = xxx.yyy  # simple assignment to a global

相对于完整程序,Python 没有真正的“全局变量”。像x = 3 这样的语句将始终修改局部变量、捕获的变量(nonlocal 声明)或全局模块。 “真正的全局”根本不存在(如果你真的需要它们,你可以做的是为全局创建一个特定的模块,并使用myglobs.var 而不是var 引用它们)。

PS:代码

def addPoint(userInstance, comment):
    global user
    userInstance = user
    message = "current name for user: " + userInstance.getName()

看起来很奇怪。参数userInstance 被覆盖。可能是你的意思

user = userInstance

改为?

【讨论】:

  • 我明白这一点,但在你的例子中,我试图将“baz”更改为“graz”,它仍然是“baz”。我该如何解决?
  • user = object1 需要更改,以便 user = object2
  • 我刚刚尝试使用classes.user = userData,但没有奏效。我还尝试了User.user = userData,但无法更改全局user
  • 更新了代码以确保准确性。将 userInstance 变量固定为全局引用。另外,我明白你在说什么,但我没有导入user 的值。它在文件的开头创建为user class 的实例,我试图将其更改为从 .pkl 文件中读取的该类的不同实例
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-02-09
相关资源
最近更新 更多