近期在读任俊和应小萍的《乐商》,从了解习得性无助,到乐商(OD)是一种可以培养的能力,很多观点给了我启发,书中主要讲的是塞利格曼的积极心理学,讨论了对事物的控制感对于人心理的影响,习得性无助可以通过增加成功体验、增加控制感来预防,既然能够预防,那乐观也同样可以习得,我对书中的一个问卷比较感兴趣,叫做“解释风格”问卷,我将他写成了一个简易的Python程序。
import re
import sys
from dataclasses import dataclass
QUESTION_TEXT = """
1. 你所负责的那项计划非常成功
A:我监督手下很严
B:每一个人都花了很多心血在上面
PsG:A1分,B0分
2. 你和配偶(男/女朋友)在吵完架后讲和了
A:我原谅了他/她
B:我一般来说是很宽宏大量,不记仇的
PmG:A0分,B1分
3. 你开车去朋友家,中途迷路了
A:我错过了一个路口没转弯
B:我朋友给我的指引讲得不清不楚
PsB:A1分,B0分
4. 你的配偶(男/女朋友)出乎意料地买了一件礼物给你
A:他/她加薪了
B:我昨晚请他/她出去吃了豪华大餐
PsG:A0分,B1分
5. 你忘记你的配偶(男/女朋友)的生日
A:我对记生日是很差劲的
B:我太忙了
PmB:A1分,B0分
6. 神秘的爱慕者送了你一束花
A:我对他/她很有吸引力
B:我的人缘很好
PvG:A0分,B1分
7. 你当选了社区的公职(民意代表)
A:我花了很多时间和精力去竞选
B:我做任何事都全力以赴
PvG:A0分,B1分
8. 你忘记了一个很重要的约会
A:我的记忆有时真是很糟糕
B:我有时会忘记去看记事本上的约会记录
PvB:A1分,B0分
9. 你竞选民意代表,结果你落选了
A:我的竞选宣传不够
B:我的对手人缘比较好
PsB:A1分,B0分
10. 你成功地主持了一个宴会
A:我那晚真是风度翩翩
B:我是一个好主人
PmG:A0分,B1分
11. 你及时报警阻止了一件犯罪
A:我听到奇怪的声音,觉得不对劲
B:我那天很警觉
PsG:A0分,B1分
12. 你这一年都很健康
A:我周围的人几乎都不生病,所以我没被传染
B:我很注意我的饮食,而且每天休息都足够
PsG:A0分,B1分
13. 你因为借书逾期未还而被图书馆罚款
A:当我全神贯注在阅读时,我常忘记借阅到期了
B:我全心在写报告上,忘记去还那本书了
PmB:A1分,B0分
14. 你买卖股票赚了不少钱
A:我的经纪人决定去试一个新的投资
B:我的经纪人是一流的
PmG:A0分,B1分
15. 你赢了运动会上的竞赛
A:我觉得我是东方不败
B:我很努力训练自己
PmG:A0分,B1分
16. 你在大考中失败了
A:我没有其他考生那么聪明
B:我准备得不够
PvB:A1分,B0分
17. 你特意为你的朋友做了一道菜,而他连尝都不尝
A:我做得不好
B:我的食谱也许不太合口味
PvB:A1分,B0分
18. 你花很长的时间练习某项运动,但在比赛时失败了
A:我不是一个好的运动员
B:我对那项运动不在行
PvB:A1分,B0分
19. 你的车子在深夜的大街上没了汽油
A:我没有事先检查一下油箱还有多少油
B:油表的指针坏了
PsB:A1分,B0分
20. 你对朋友发了一顿脾气
A:他/她总是烦我
B:他/她今天很不友善
PmB:A1分,B0分
21. 你因为没有申报个人所得税而受罚
A:我总是拖着不愿去办有关所得税的事
B:我今年很懒散,不想报税
PmB:A1分,B0分
22. 你约一个人出去玩,但他/她拒绝了你
A:我那一天什么事都做不成,心情恶劣
B:我去约他/她时紧张得说不出话来
PvB:A1分,B0分
23. 一个现场节目的主持人从众多的观众中,单挑了你上台去参加节目
A:我坐的位置比较好
B:我表现得最热心
PsG:A0分,B1分
24. 你在舞会上很热门,常有人请你跳舞
A:我在舞会上很活跃
B:那一晚我所有表现都十全十美
PmG:A1分,B0分
25. 你替你的配偶(男/女朋友)买了一件礼物,而他/她并不喜欢
A:我没有好好用心思去想应该买什么
B:他/她是个很挑剔的人
PsB:A1分,B0分
26. 你在应聘时的面试上表现得很好
A:我在面试时觉得非常自信
B:我很会面试
PmG:A0分,B1分
27. 你说了一个笑话,每个人都捧腹大笑
A:这个笑话很好笑
B:我说笑话说得很好,时间拿捏得很准
PsG:A0分,B1分
28. 你的老板只给你一点点时间去完成一个计划,但是你还是如期达成了
A:我对我的工作很内行
B:我是一个很有效率的人
PvG:A0分,B1分
29. 你最近觉得很疲倦
A:我从来都没有机会放松一下
B:我这个礼拜特别忙
PmB:A1分,B0分
30. 你邀请某个人跳舞,他/她拒绝了
A:我不是一个好的舞者
B:他/她不喜欢跳舞
PsB:A1分,B0分
31. 你救了一个人使他没有噎死
A:我知道如何急救哽噎的人,我会这个技术
B:我知道在紧急的情况如何处理
PvG:A0分,B1分
32. 你的热恋情侶想要冷静疏远一阵子
A:我太自我中心了
B:我花在他/她身上的时间不够
PvB:A1分,B0分
33. 一个朋友说了一些使你伤心的话
A:他/她说话每次不经过大脑就冲口而出
B:他/她心情不好,把气出在我身上
PmB:A1分,B0分
34. 你的老板来找你,要你给他忠告
A:我是这个领域的专家
B:我给的忠告一向都切实可行
PvG:A0分,B1分
35. 一个朋友谢谢你帮助他/她走过一段困难时期
A:我很乐意协助朋友度过困难期
B:我关心朋友
PvG:A0分,B1分
36. 你在宴会上玩得很痛快
A:这里的每一个人都很友善
B:我很友善
PsG:A0分,B1分
37. 你的医生说你的身体健康情况极佳
A:我坚持经常运动
B:我对健康很小心也很注意
PvG:A0分,B1分
38. 你的配偶(男/女朋友)带你去度一个罗曼蒂克的周末
A:他/她需要远离城市几天
B:他/她喜欢去看看新的、没去过的地方
PmG:A0分,B1分
39. 你的医生说你吃太多甜的东西
A:我对饮食不大注意
B:我避免不了糖分,到处都是甜品,每样东西里都有糖
PsB:A1分,B0分
40. 老板指派你去做一个重要计划的主持人
A:我才刚刚成功地做完一个类似的计划
B:我是好的计划主持人,监督严谨,沟通良好
PmG:A0分,B1分
41. 你和你的配偶(男/女朋友)最近一直吵架
A:我最近压力很大,心情不好
B:他/她最近心情恶劣
PsB:A1分,B0分
42. 你滑雪时总是摔跤
A:滑雪很困难
B:滑雪道结冰了很溜滑
PmB:A1分,B0分
43. 你赢得了一个很好的大奖
A:我解决了一个重大的难题
B:我是最好的员工
PvG:A0分,B1分
44. 你买的股票现在跌入谷底
A:我那个时候对商业投资不是很懂
B:我买错了股票
PvB:A1分,B0分
45. 我中了奖券(大乐透)
A:真是运气
B:我选对了号码
PsG:A0分,B1分
46. 你在放假时胖了起来,现在瘦不回去
A:就长远来说,节食是没有用的
B:我这次用的这个减肥法没效
PmB:A0分,B1分
47. 你生病住院,但是没什么人来看你
A:我在生病的时候脾气不好
B:我的朋友常会疏忽像探病这种事
PsB:A1分,B0分
48. 商店拒收你的信用卡
A:我有时高估了自己的信用额度
B:我有时候忘记去付信用卡账单
PvB:A1分,B0分
"""
@dataclass(frozen=True)
class Question:
number: int
scale: str
prompt: str
option_a: str
option_b: str
score_a: int
score_b: int
@dataclass(frozen=True)
class Band:
minimum: int | None = None
maximum: int | None = None
label: str = ""
brief: str = ""
def matches(self, score: int) -> bool:
if self.minimum is not None and score < self.minimum:
return False
if self.maximum is not None and score > self.maximum:
return False
return True
SCALE_LABELS = {
"PmB": "PmB 坏事件永久性",
"PvB": "PvB 坏事件普遍性",
"PsB": "PsB 坏事件个人化",
"PmG": "PmG 好事件永久性",
"PvG": "PvG 好事件普遍性",
"PsG": "PsG 好事件个人化",
}
SCALE_EXPLANATIONS = {
"PmB": "Permanence of Bad,表示你是否把坏事看成长期、难改变的状态。",
"PvB": "Pervasiveness of Bad,表示你是否把一次挫折泛化到很多生活领域。",
"PsB": "Personalization of Bad,表示你是否倾向把坏结果归因为自己的缺陷。",
"PmG": "Permanence of Good,表示你是否相信好结果能够持续和延续。",
"PvG": "Pervasiveness of Good,表示你是否能把好事扩展到更多生活领域。",
"PsG": "Personalization of Good,表示你是否愿意把成功归因为自己的能力和努力。",
}
SCALE_BANDS = {
"PmB": [
Band(0, 1, "非常乐观", "高乐商"),
Band(2, 3, "中等乐观", "良好乐商"),
Band(4, 4, "一般", "中等乐商"),
Band(5, 6, "中度悲观", "轻度低乐商"),
Band(7, 8, "重度悲观", "重度低乐商"),
],
"PvB": [
Band(0, 1, "非常乐观", "高乐商"),
Band(2, 3, "中等乐观", "良好乐商"),
Band(4, 4, "一般", "一般乐商"),
Band(5, 6, "中度悲观", "轻度低乐商"),
Band(7, 8, "非常悲观", "重度低乐商"),
],
"PsB": [
Band(0, 1, "自视很高", "高乐商"),
Band(2, 3, "中等自傲", "良好乐商"),
Band(4, 4, "自视一般", "一般乐商"),
Band(5, 6, "中度自卑", "轻度低乐商"),
Band(7, 8, "极度自卑", "重度低乐商"),
],
"PmG": [
Band(7, 8, "非常乐观", "高乐商"),
Band(6, 6, "中度乐观", "良好乐商"),
Band(4, 5, "一般", "一般乐商"),
Band(3, 3, "中度悲观", "轻度低乐商"),
Band(0, 2, "重度悲观", "重度低乐商"),
],
"PvG": [
Band(7, 8, "非常乐观", "较高乐商"),
Band(6, 6, "中等乐观", "良好乐商"),
Band(4, 5, "一般", "中等乐商"),
Band(3, 3, "中等悲观", "轻度低乐商"),
Band(0, 2, "非常悲观", "重度低乐商"),
],
"PsG": [
Band(7, 8, "非常乐观", "高乐商"),
Band(6, 6, "中度乐观", "中等乐商"),
Band(4, 5, "一般", "一般乐商"),
Band(3, 3, "中度悲观", "轻度低乐商"),
Band(0, 2, "极度悲观", "重度低乐商"),
],
}
GB_BANDS = [
Band(9, None, "很乐观", "高乐商"),
Band(6, 8, "中等程度乐观", "较高乐商"),
Band(3, 5, "一般性乐观", "一般乐商"),
Band(1, 2, "中等悲观", "轻度低乐商"),
Band(None, 0, "极端悲观", "重度低乐商"),
]
def load_questions(text: str) -> list[Question]:
lines = [line.strip() for line in text.splitlines() if line.strip()]
questions: list[Question] = []
i = 0
while i < len(lines):
match = re.match(r"^(\d+)\.\s*(.+)$", lines[i])
if not match:
i += 1
continue
number = int(match.group(1))
prompt = match.group(2).strip()
a_line = lines[i + 1]
b_line = lines[i + 2]
score_line = lines[i + 3]
a_match = re.match(r"^A[::]\s*(.+)$", a_line)
b_match = re.match(r"^B[::]\s*(.+)$", b_line)
score_match = re.match(
r"^(PmB|PvB|PsB|PmG|PvG|PsG)[::]\s*A\s*(\d)\s*分[,,]\s*B\s*(\d)\s*分$",
score_line,
)
if not a_match or not b_match or not score_match:
raise ValueError(f"第 {number} 题格式错误。")
questions.append(
Question(
number=number,
scale=score_match.group(1),
prompt=prompt,
option_a=a_match.group(1).strip(),
option_b=b_match.group(1).strip(),
score_a=int(score_match.group(2)),
score_b=int(score_match.group(3)),
)
)
i += 4
if len(questions) != 48:
raise ValueError(f"题目数量错误:{len(questions)}")
return questions
def ask_choice(question: Question, total: int) -> str:
print(f"\n第 {question.number}/{total} 题")
print(question.prompt)
print(f"A. {question.option_a}")
print(f"B. {question.option_b}")
while True:
choice = input("> ").strip().upper()
if choice in {"A", "B"}:
return choice
def get_band(scale: str, score: int) -> Band:
for band in SCALE_BANDS[scale]:
if band.matches(score):
return band
raise ValueError(f"未找到 {scale} 的分档:{score}")
def get_gb_band(score: int) -> Band:
for band in GB_BANDS:
if band.matches(score):
return band
raise ValueError(f"未找到 G-B 的分档:{score}")
def interpret_scale(scale: str, score: int) -> list[str]:
band = get_band(scale, score)
return [
f"{SCALE_LABELS[scale]}:{score}/8",
f"分档:{band.label},对应 {band.brief}。",
f"{SCALE_EXPLANATIONS[scale]}",
]
def interpret_overall(scores: dict[str, int]) -> list[str]:
bad_total = scores["PmB"] + scores["PvB"] + scores["PsB"]
good_total = scores["PmG"] + scores["PvG"] + scores["PsG"]
gb = good_total - bad_total
band = get_gb_band(gb)
if gb >= 6:
summary = "整体上更倾向于把好事内化并推广,把坏事看得较不持久。"
elif gb >= 1:
summary = "整体解释风格略偏积极,但在压力情境下仍可能出现悲观归因。"
else:
summary = "整体解释风格偏悲观,更容易把挫折看得持久、普遍,或更多归到自己身上。"
return [
f"G-B:{gb}",
f"总体分档:{band.label},对应 {band.brief}。",
f"坏事件总分:{bad_total}/24,好事件总分:{good_total}/24。",
summary
]
def main() -> None:
if hasattr(sys.stdin, "reconfigure"):
sys.stdin.reconfigure(encoding="utf-8")
if hasattr(sys.stdout, "reconfigure"):
sys.stdout.reconfigure(encoding="utf-8")
questions = load_questions(QUESTION_TEXT)
scores = {key: 0 for key in SCALE_LABELS}
for question in questions:
choice = ask_choice(question, len(questions))
scores[question.scale] += question.score_a if choice == "A" else question.score_b
print("\n结果")
for scale in ["PmB", "PvB", "PsB", "PmG", "PvG", "PsG"]:
for line in interpret_scale(scale, scores[scale]):
print(line)
print()
for line in interpret_overall(scores):
print(line)
if __name__ == "__main__":
main()
评论
0 条