Memory Efficiency in wattpad
¶
This package strives to be resource efficient. This is done through the implementation of:
- The Singleton Design Pattern
- Caching for HTTP Requests
Singletons¶
To begin, let's discuss Singletons in wattpad
.
A Singleton is a class that when instantiated, always points to the same instance in memory. That means, a new object is never made if one exists already.
The wattpad.User
, wattpad.Story
, and wattpad.List
classes are all singletons for the identifier they're initialized with. That is, a User
classes are singletons based on username, and Story
and List
for their ID.
from rich import print
from wattpad import User
one = User("WattpadBooks")
print(one)
<User username=wattpadbooks>
Documentation for methods and attributes for all classes is available here. You can also use Python's help()
function.
help(one)
Help on User in module wattpad.wattpad object: class User(builtins.object) | User(*args, **kwargs) | | A representation of a User on Wattpad. | **Note**: Users are singletons, unique as per their username. Two user classes with the same username are the _same_. | | Attributes: | username (str): Lowercased username of this User. | stories (list[Story]): Stories authored by this User. | followers (list[User]): Users that follow this User. | following (list[User]): Users this User follows. | lists (list[List]): Lists created by this User. | data (UserModel): User Data from the Wattpad API. | | Methods defined here: | | __init__(self, username: 'str', **kwargs) | Create a User object. | | Args: | username (str): The username of this User. | **kwargs (any): Arguments to pass directly to the underlying `UserModel`. These are ignored if the User has been instantiated earlier in the runtime. | | __repr__(self) -> 'str' | Return repr(self). | | async fetch(self, include: 'bool | UserModelFieldsType' = False) -> 'dict' | Populates a User's data. Call this method after instantiation. | | Args: | include (bool | UserModelFieldsType, optional): Fields to fetch. True fetches all fields. Defaults to False. | | Returns: | dict: The raw API Response. | | async fetch_followers(self, include: 'bool | UserModelFieldsType' = False, limit: 'Optional[int]' = None, offset: 'Optional[int]' = None) -> 'dict' | Fetches the User's followers. | | Args: | include (bool | UserModelFieldsType, optional): Fields of the following users' to fetch. True fetches all fields. Defaults to False. | limit (Optional[int], optional): Maximum number of users to return at once. Use this alongside `offset` for better performance. Defaults to None. | offset (Optional[int], optional): Number of users to skip before returning followers. Use this alongside `limit` for better performance. Defaults to None. | | Returns: | dict: The raw API Response. | | async fetch_following(self, include: 'bool | UserModelFieldsType' = False, limit: 'Optional[int]' = None, offset: 'Optional[int]' = None) -> 'dict' | Fetch the users this User follows. | | Args: | include (bool | UserModelFieldsType, optional): Fields of the followed users' to fetch. True fetches all fields. Defaults to False. | limit (Optional[int], optional): Maximum number of users to return at once. Use this alongside `offset` for better performance. Defaults to None. | offset (Optional[int], optional): Number of users to skip before returning followers. Use this alongside `limit` for better performance. Defaults to None. | | Returns: | dict: The raw API Response. | | async fetch_lists(self, include: 'bool | ListModelFieldsType' = False, limit: 'Optional[int]' = None, offset: 'Optional[int]' = None) -> 'dict' | Fetch a User's lists. | | Args: | include (bool | ListModelFieldsType, optional): Fields of the lists to fetch. True fetches all fields. Defaults to False. | limit (Optional[int], optional): Maximum number of users to return at once. Use this alongside `offset` for better performance. Defaults to None. | offset (Optional[int], optional): Number of users to skip before returning followers. Use this alongside `limit` for better performance. Defaults to None. | | Returns: | dict: The raw API Response. | | async fetch_stories(self, include: 'bool | StoryModelFieldsType' = False) -> 'dict' | Fetch a User's authored stories. | | Args: | include (bool | StoryModelFieldsType, optional): Fields of authored stories to fetch. True fetches all fields. Defaults to False. | | Returns: | dict: The raw API Response. | | ---------------------------------------------------------------------- | Data descriptors defined here: | | __dict__ | dictionary for instance variables (if defined) | | __weakref__ | list of weak references to the object (if defined) | | ---------------------------------------------------------------------- | Data and other attributes defined here: | | __annotations__ = {}
Let's try each of these methods:
fetch
fetch_following
fetch_followers
fetch_lists
fetch_stories
raw_data = await one.fetch()
print(raw_data)
{ 'avatar': 'https://img.wattpad.com/useravatar/WattpadBooks.128.888605.jpg', 'isPrivate': False, 'backgroundUrl': 'https://img.wattpad.com/userbg/WattpadBooks.38113.jpg', 'name': 'Wattpad Books', 'description': "Wattpad Books brings stories the world needs to hear, brought to life by your favorite writers, right into your hands. Welcome home. 🏡🧡\n\nStay in the know of all the latest launches from Wattpad Books. Looking for your next literary obsession? Crossing your fingers for more work from your favorite creator? Follow us here to be the first to hear about new releases, author interviews, and more!\n\nWe see your dreams, and we want to help you achieve them. If you're hoping to get published, our advice is to keep doing what you love: writing. Every book published by Wattpad Books was born right here on Wattpad. ⭐️\n\n🔈Follow Wattpad Books:\nTwitter: twitter.com/wattpadbooks\nInstagram: wattpadbooks\nFacebook: facebook.com/wattpad", 'status': '', 'gender': 'Other', 'genderCode': 'O', 'language': 1, 'locale': 'en_US', 'createDate': '2019-01-23T21:14:00Z', 'modifyDate': '2020-07-10T20:29:59Z', 'location': 'Toronto, Canada', 'verified': True, 'ambassador': False, 'facebook': '', 'twitter': '', 'website': 'books.wattpad.com', 'lulu': '', 'smashwords': '', 'bubok': '', 'votesReceived': 1688, 'numStoriesPublished': 6, 'numFollowing': 1, 'numFollowers': 60837, 'numMessages': 2004, 'numLists': 6, 'verified_email': True, 'preferred_categories': [], 'allowCrawler': True, 'deeplink': 'https://www.wattpad.com/WattpadBooks', 'isMuted': False }
All fetch
methods return the raw JSON parsed from the Wattpad API.
For normal usage, it's recommended to use the class attributes:
print(one.data.description)
Wattpad Books brings stories the world needs to hear, brought to life by your favorite writers, right into your hands. Welcome home. 🏡🧡 Stay in the know of all the latest launches from Wattpad Books. Looking for your next literary obsession? Crossing your fingers for more work from your favorite creator? Follow us here to be the first to hear about new releases, author interviews, and more! We see your dreams, and we want to help you achieve them. If you're hoping to get published, our advice is to keep doing what you love: writing. Every book published by Wattpad Books was born right here on Wattpad. ⭐️ 🔈Follow Wattpad Books: Twitter: twitter.com/wattpadbooks Instagram: wattpadbooks Facebook: facebook.com/wattpad
A list of available attributes can be found here on the model_types
page. You can also view wattpad.models.UserModel.model_fields
for the same.
from wattpad.models import UserModel
print(UserModel.model_fields)
{ 'username': FieldInfo(annotation=str, required=True), 'avatar': FieldInfo(annotation=Union[str, NoneType], required=False), 'is_private': FieldInfo( annotation=Union[bool, NoneType], required=False, alias='isPrivate', alias_priority=2 ), 'background_url': FieldInfo( annotation=Union[str, NoneType], required=False, alias='backgroundUrl', alias_priority=2 ), 'follower': FieldInfo(annotation=Union[bool, NoneType], required=False), 'following': FieldInfo(annotation=Union[bool, NoneType], required=False), 'name': FieldInfo(annotation=Union[str, NoneType], required=False), 'description': FieldInfo(annotation=Union[str, NoneType], required=False), 'status': FieldInfo(annotation=Union[str, NoneType], required=False), 'gender': FieldInfo(annotation=Union[str, NoneType], required=False), 'gender_code': FieldInfo( annotation=Union[str, NoneType], required=False, alias='genderCode', alias_priority=2 ), 'language': FieldInfo(annotation=Union[int, NoneType], required=False), 'locale': FieldInfo(annotation=Union[str, NoneType], required=False), 'create_date': FieldInfo( annotation=Union[str, NoneType], required=False, alias='createDate', alias_priority=2 ), 'modify_date': FieldInfo( annotation=Union[str, NoneType], required=False, alias='modifyDate', alias_priority=2 ), 'location': FieldInfo(annotation=Union[str, NoneType], required=False), 'verified': FieldInfo(annotation=Union[bool, NoneType], required=False), 'ambassador': FieldInfo(annotation=Union[bool, NoneType], required=False), 'facebook': FieldInfo(annotation=Union[str, NoneType], required=False), 'twitter': FieldInfo(annotation=Union[str, NoneType], required=False), 'website': FieldInfo(annotation=Union[str, NoneType], required=False), 'lulu': FieldInfo(annotation=Union[str, NoneType], required=False), 'smashwords': FieldInfo(annotation=Union[str, NoneType], required=False), 'bubok': FieldInfo(annotation=Union[str, NoneType], required=False), 'votes_received': FieldInfo( annotation=Union[int, NoneType], required=False, alias='votesReceived', alias_priority=2 ), 'num_stories_published': FieldInfo( annotation=Union[int, NoneType], required=False, alias='numStoriesPublished', alias_priority=2 ), 'num_following': FieldInfo( annotation=Union[int, NoneType], required=False, alias='numFollowing', alias_priority=2 ), 'num_followers': FieldInfo( annotation=Union[int, NoneType], required=False, alias='numFollowers', alias_priority=2 ), 'num_messages': FieldInfo( annotation=Union[int, NoneType], required=False, alias='numMessages', alias_priority=2 ), 'num_lists': FieldInfo(annotation=Union[int, NoneType], required=False, alias='numLists', alias_priority=2), 'verified_email': FieldInfo(annotation=Union[bool, NoneType], required=False), 'preferred_categories': FieldInfo(annotation=Union[List, NoneType], required=False), 'allow_crawler': FieldInfo( annotation=Union[bool, NoneType], required=False, alias='allowCrawler', alias_priority=2 ), 'deeplink': FieldInfo(annotation=Union[str, NoneType], required=False), 'is_muted': FieldInfo(annotation=Union[bool, NoneType], required=False, alias='isMuted', alias_priority=2), 'birthdate': FieldInfo(annotation=Union[str, NoneType], required=False), 'inbox': FieldInfo(annotation=Union[InboxModel, NoneType], required=False), 'notifications': FieldInfo(annotation=Union[NotificationsModel, NoneType], required=False), 'connected_services': FieldInfo( annotation=Union[ConnectedServicesModel, NoneType], required=False, alias='connectedServices', alias_priority=2 ), 'age': FieldInfo(annotation=Union[int, NoneType], required=False), 'email': FieldInfo(annotation=Union[str, NoneType], required=False), 'has_password': FieldInfo(annotation=Union[bool, NoneType], required=False) }
Now, let's delve into the main subject of this notebook: Memory Efficiency in the wattpad
package.
one
<User username=wattpadbooks>
two = User("Wattpad")
three = User("wAttPadBOOKS")
We've instantiated two new User objects, one for the Wattpad
account, and once more for WattpadBooks
, which we've instantiated before into the one
variable.
print(id(one))
print(id(two))
print(id(three))
140584630579888
140584061227776
140584630579888
one
and three
have the same IDs, that means they reference the same location in memory, whereas two
has a unique ID.
This means that one
and three
are the same.
Let's verify this:
one.who_am_i = "this_is_one"
print("one: ", getattr(one, "who_am_i", None))
print("two: ", getattr(two, "who_am_i", None))
print("three: ", getattr(three, "who_am_i", None))
one: this_is_one
two: None
three: this_is_one
It's evident that three
has the attributes we assigned to one
, whereas two
doesn't.
User
s with the same Username are the same.
We haven't fetched any data for two
or three
, let's see what they contain so far:
print(two.data)
UserModel( username='wattpad', avatar=None, is_private=None, background_url=None, follower=None, following=None, name=None, description=None, status=None, gender=None, gender_code=None, language=None, locale=None, create_date=None, modify_date=None, location=None, verified=None, ambassador=None, facebook=None, twitter=None, website=None, lulu=None, smashwords=None, bubok=None, votes_received=None, num_stories_published=None, num_following=None, num_followers=None, num_messages=None, num_lists=None, verified_email=None, preferred_categories=None, allow_crawler=None, deeplink=None, is_muted=None, birthdate=None, inbox=None, notifications=None, connected_services=None, age=None, email=None, has_password=None )
two
is as empty as it can be. Let's take a look at three
(which has the same username as one
.)
print(three.data)
UserModel( username='wattpadbooks', avatar='https://img.wattpad.com/useravatar/WattpadBooks.128.888605.jpg', is_private=False, background_url='https://img.wattpad.com/userbg/WattpadBooks.38113.jpg', follower=None, following=None, name='Wattpad Books', description="Wattpad Books brings stories the world needs to hear, brought to life by your favorite writers, right into your hands. Welcome home. 🏡🧡\n\nStay in the know of all the latest launches from Wattpad Books. Looking for your next literary obsession? Crossing your fingers for more work from your favorite creator? Follow us here to be the first to hear about new releases, author interviews, and more!\n\nWe see your dreams, and we want to help you achieve them. If you're hoping to get published, our advice is to keep doing what you love: writing. Every book published by Wattpad Books was born right here on Wattpad. ⭐️\n\n🔈Follow Wattpad Books:\nTwitter: twitter.com/wattpadbooks\nInstagram: wattpadbooks\nFacebook: facebook.com/wattpad", status='', gender='Other', gender_code='O', language=1, locale='en_US', create_date='2019-01-23T21:14:00Z', modify_date='2020-07-10T20:29:59Z', location='Toronto, Canada', verified=True, ambassador=False, facebook='', twitter='', website='books.wattpad.com', lulu='', smashwords='', bubok='', votes_received=1688, num_stories_published=6, num_following=1, num_followers=60837, num_messages=2004, num_lists=6, verified_email=True, preferred_categories=[], allow_crawler=True, deeplink='https://www.wattpad.com/WattpadBooks', is_muted=False, birthdate=None, inbox=None, notifications=None, connected_services=None, age=None, email=None, has_password=None )
There we go, without fetching any data, three
is already populated. This is because we fetched data for one
earlier, and one
and three
are the same.
Note: Deleting one
will not delete three
. To completely delete an object, remove all references to it in your code.
That's all. If you need help, look here.
TheOnlyWayUp © 2024